2012-06-13 13:12:41 +08:00
|
|
|
//===- TableGenBackends.h - Declarations for Clang TableGen Backends ------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file contains the declarations for all of the Clang TableGen
|
|
|
|
// backends. A "TableGen backend" is just a function. See
|
|
|
|
// "$LLVM_ROOT/utils/TableGen/TableGenBackends.h" for more info.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2014-08-08 21:24:19 +08:00
|
|
|
#ifndef LLVM_CLANG_UTILS_TABLEGEN_TABLEGENBACKENDS_H
|
|
|
|
#define LLVM_CLANG_UTILS_TABLEGEN_TABLEGENBACKENDS_H
|
|
|
|
|
2012-06-13 13:12:41 +08:00
|
|
|
#include <string>
|
|
|
|
|
|
|
|
namespace llvm {
|
|
|
|
class raw_ostream;
|
|
|
|
class RecordKeeper;
|
|
|
|
}
|
|
|
|
|
|
|
|
using llvm::raw_ostream;
|
|
|
|
using llvm::RecordKeeper;
|
|
|
|
|
|
|
|
namespace clang {
|
|
|
|
|
|
|
|
void EmitClangDeclContext(RecordKeeper &RK, raw_ostream &OS);
|
|
|
|
void EmitClangASTNodes(RecordKeeper &RK, raw_ostream &OS,
|
|
|
|
const std::string &N, const std::string &S);
|
|
|
|
|
2014-01-30 06:13:45 +08:00
|
|
|
void EmitClangAttrParserStringSwitches(RecordKeeper &Records, raw_ostream &OS);
|
2017-04-18 22:33:39 +08:00
|
|
|
void EmitClangAttrSubjectMatchRulesParserStringSwitches(RecordKeeper &Records,
|
|
|
|
raw_ostream &OS);
|
2012-06-13 13:12:41 +08:00
|
|
|
void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS);
|
|
|
|
void EmitClangAttrImpl(RecordKeeper &Records, raw_ostream &OS);
|
|
|
|
void EmitClangAttrList(RecordKeeper &Records, raw_ostream &OS);
|
2017-04-18 22:33:39 +08:00
|
|
|
void EmitClangAttrSubjectMatchRuleList(RecordKeeper &Records, raw_ostream &OS);
|
2012-06-13 13:12:41 +08:00
|
|
|
void EmitClangAttrPCHRead(RecordKeeper &Records, raw_ostream &OS);
|
|
|
|
void EmitClangAttrPCHWrite(RecordKeeper &Records, raw_ostream &OS);
|
2014-03-31 21:14:44 +08:00
|
|
|
void EmitClangAttrHasAttrImpl(RecordKeeper &Records, raw_ostream &OS);
|
2013-01-25 00:46:58 +08:00
|
|
|
void EmitClangAttrSpellingListIndex(RecordKeeper &Records, raw_ostream &OS);
|
2013-12-31 01:24:36 +08:00
|
|
|
void EmitClangAttrASTVisitor(RecordKeeper &Records, raw_ostream &OS);
|
2012-06-13 13:12:41 +08:00
|
|
|
void EmitClangAttrTemplateInstantiate(RecordKeeper &Records, raw_ostream &OS);
|
|
|
|
void EmitClangAttrParsedAttrList(RecordKeeper &Records, raw_ostream &OS);
|
2013-09-10 07:33:17 +08:00
|
|
|
void EmitClangAttrParsedAttrImpl(RecordKeeper &Records, raw_ostream &OS);
|
2012-06-13 13:12:41 +08:00
|
|
|
void EmitClangAttrParsedAttrKinds(RecordKeeper &Records, raw_ostream &OS);
|
2013-01-08 01:53:08 +08:00
|
|
|
void EmitClangAttrDump(RecordKeeper &Records, raw_ostream &OS);
|
2012-06-13 13:12:41 +08:00
|
|
|
|
|
|
|
void EmitClangDiagsDefs(RecordKeeper &Records, raw_ostream &OS,
|
|
|
|
const std::string &Component);
|
|
|
|
void EmitClangDiagGroups(RecordKeeper &Records, raw_ostream &OS);
|
|
|
|
void EmitClangDiagsIndexName(RecordKeeper &Records, raw_ostream &OS);
|
|
|
|
|
|
|
|
void EmitClangSACheckers(RecordKeeper &Records, raw_ostream &OS);
|
|
|
|
|
2012-08-31 10:21:44 +08:00
|
|
|
void EmitClangCommentHTMLTags(RecordKeeper &Records, raw_ostream &OS);
|
|
|
|
void EmitClangCommentHTMLTagsProperties(RecordKeeper &Records, raw_ostream &OS);
|
2013-01-30 22:29:28 +08:00
|
|
|
void EmitClangCommentHTMLNamedCharacterReferences(RecordKeeper &Records, raw_ostream &OS);
|
2012-08-31 10:21:44 +08:00
|
|
|
|
2012-09-11 04:32:42 +08:00
|
|
|
void EmitClangCommentCommandInfo(RecordKeeper &Records, raw_ostream &OS);
|
2013-02-02 04:23:57 +08:00
|
|
|
void EmitClangCommentCommandList(RecordKeeper &Records, raw_ostream &OS);
|
2012-09-11 04:32:42 +08:00
|
|
|
|
2012-06-13 13:12:41 +08:00
|
|
|
void EmitNeon(RecordKeeper &Records, raw_ostream &OS);
|
2018-01-20 07:11:18 +08:00
|
|
|
void EmitFP16(RecordKeeper &Records, raw_ostream &OS);
|
2012-06-13 13:12:41 +08:00
|
|
|
void EmitNeonSema(RecordKeeper &Records, raw_ostream &OS);
|
|
|
|
void EmitNeonTest(RecordKeeper &Records, raw_ostream &OS);
|
Rewrite ARM NEON intrinsic emission completely.
There comes a time in the life of any amateur code generator when dumb string
concatenation just won't cut it any more. For NeonEmitter.cpp, that time has
come.
There were a bunch of magic type codes which meant different things depending on
the context. There were a bunch of special cases that really had no reason to be
there but the whole thing was so creaky that removing them would cause something
weird to fall over. There was a 1000 line switch statement for code generation
involving string concatenation, which actually did lexical scoping to an extent
(!!) with a bunch of semi-repeated cases.
I tried to refactor this three times in three different ways without
success. The only way forward was to rewrite the entire thing. Luckily the
testing coverage on this stuff is absolutely massive, both with regression tests
and the "emperor" random test case generator.
The main change is that previously, in arm_neon.td a bunch of "Operation"s were
defined with special names. NeonEmitter.cpp knew about these Operations and
would emit code based on a huge switch. Actually this doesn't make much sense -
the type information was held as strings, so type checking was impossible. Also
TableGen's DAG type actually suits this sort of code generation very well
(surprising that...)
So now every operation is defined in terms of TableGen DAGs. There are a bunch
of operators to use, including "op" (a generic unary or binary operator), "call"
(to call other intrinsics) and "shuffle" (take a guess...). One of the main
advantages of this apart from making it more obvious what is going on, is that
we have proper type inference. This has two obvious advantages:
1) TableGen can error on bad intrinsic definitions easier, instead of just
generating wrong code.
2) Calls to other intrinsics are typechecked too. So
we no longer need to work out whether the thing we call needs to be the Q-lane
version or the D-lane version - TableGen knows that itself!
Here's an example: before:
case OpAbdl: {
std::string abd = MangleName("vabd", typestr, ClassS) + "(__a, __b)";
if (typestr[0] != 'U') {
// vabd results are always unsigned and must be zero-extended.
std::string utype = "U" + typestr.str();
s += "(" + TypeString(proto[0], typestr) + ")";
abd = "(" + TypeString('d', utype) + ")" + abd;
s += Extend(utype, abd) + ";";
} else {
s += Extend(typestr, abd) + ";";
}
break;
}
after:
def OP_ABDL : Op<(cast "R", (call "vmovl", (cast $p0, "U",
(call "vabd", $p0, $p1))))>;
As an example of what happens if you do something wrong now, here's what happens
if you make $p0 unsigned before the call to "vabd" - that is, $p0 -> (cast "U",
$p0):
arm_neon.td:574:1: error: No compatible intrinsic found - looking up intrinsic 'vabd(uint8x8_t, int8x8_t)'
Available overloads:
- float64x2_t vabdq_v(float64x2_t, float64x2_t)
- float64x1_t vabd_v(float64x1_t, float64x1_t)
- float64_t vabdd_f64(float64_t, float64_t)
- float32_t vabds_f32(float32_t, float32_t)
... snip ...
This makes it seriously easy to work out what you've done wrong in fairly nasty
intrinsics.
As part of this I've massively beefed up the documentation in arm_neon.td too.
Things still to do / on the radar:
- Testcase generation. This was implemented in the previous version and not in
the new one, because
- Autogenerated tests are not being run. The testcase in test/ differs from
the autogenerated version.
- There were a whole slew of special cases in the testcase generation that just
felt (and looked) like hacks.
If someone really feels strongly about this, I can try and reimplement it too.
- Big endian. That's coming soon and should be a very small diff on top of this one.
llvm-svn: 211101
2014-06-17 21:11:27 +08:00
|
|
|
void EmitNeon2(RecordKeeper &Records, raw_ostream &OS);
|
|
|
|
void EmitNeonSema2(RecordKeeper &Records, raw_ostream &OS);
|
|
|
|
void EmitNeonTest2(RecordKeeper &Records, raw_ostream &OS);
|
2012-06-13 13:12:41 +08:00
|
|
|
|
2014-02-17 23:27:10 +08:00
|
|
|
void EmitClangAttrDocs(RecordKeeper &Records, raw_ostream &OS);
|
2016-09-12 13:58:29 +08:00
|
|
|
void EmitClangDiagDocs(RecordKeeper &Records, raw_ostream &OS);
|
2017-01-25 03:39:46 +08:00
|
|
|
void EmitClangOptDocs(RecordKeeper &Records, raw_ostream &OS);
|
2014-02-17 23:27:10 +08:00
|
|
|
|
2017-09-06 21:20:51 +08:00
|
|
|
void EmitClangDataCollectors(RecordKeeper &Records, raw_ostream &OS);
|
|
|
|
|
2017-04-18 22:33:39 +08:00
|
|
|
void EmitTestPragmaAttributeSupportedAttributes(RecordKeeper &Records,
|
|
|
|
raw_ostream &OS);
|
|
|
|
|
2012-06-13 13:12:41 +08:00
|
|
|
} // end namespace clang
|
2014-08-08 21:24:19 +08:00
|
|
|
|
|
|
|
#endif
|