// Emits the code to write an attribute to a precompiled header. void EmitClangAttrPCHWrite(RecordKeeper &Records, raw_ostream &OS) { Record *InhClass = Records.getClass("InheritableAttr"); std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), Args; std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ai, ae; OS << " switch (A->getKind()) {\n"; OS << " default:\n"; OS << " llvm_unreachable(\"Unknown attribute kind!\");\n"; OS << " break;\n"; for (; i != e; ++i) { Record &R = **i; if (!R.getValueAsBit("ASTNode")) continue; OS << " case attr::" << R.getName() << ": {\n"; Args = R.getValueAsListOfDefs("Args"); if (R.isSubClassOf(InhClass) || !Args.empty()) OS << " const " << R.getName() << "Attr *SA = cast<" << R.getName() << "Attr>(A);\n"; if (R.isSubClassOf(InhClass)) OS << " Record.push_back(SA->isInherited());\n"; for (ai = Args.begin(), ae = Args.end(); ai != ae; ++ai) createArgument(**ai, R.getName())->writePCHWrite(OS); OS << " break;\n"; OS << " }\n"; } OS << " }\n"; }
CodeGenRegBank::CodeGenRegBank(RecordKeeper &Records) : Records(Records) { // Configure register Sets to understand register classes and tuples. Sets.addFieldExpander("RegisterClass", "MemberList"); Sets.addFieldExpander("CalleeSavedRegs", "SaveList"); Sets.addExpander("RegisterTuples", new TupleExpander()); // Read in the user-defined (named) sub-register indices. // More indices will be synthesized later. std::vector<Record*> SRIs = Records.getAllDerivedDefinitions("SubRegIndex"); std::sort(SRIs.begin(), SRIs.end(), LessRecord()); NumNamedIndices = SRIs.size(); for (unsigned i = 0, e = SRIs.size(); i != e; ++i) getSubRegIdx(SRIs[i]); // Build composite maps from ComposedOf fields. for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i) SubRegIndices[i]->updateComponents(*this); // Read in the register definitions. std::vector<Record*> Regs = Records.getAllDerivedDefinitions("Register"); std::sort(Regs.begin(), Regs.end(), LessRecord()); Registers.reserve(Regs.size()); // Assign the enumeration values. for (unsigned i = 0, e = Regs.size(); i != e; ++i) getReg(Regs[i]); // Expand tuples and number the new registers. std::vector<Record*> Tups = Records.getAllDerivedDefinitions("RegisterTuples"); for (unsigned i = 0, e = Tups.size(); i != e; ++i) { const std::vector<Record*> *TupRegs = Sets.expand(Tups[i]); for (unsigned j = 0, je = TupRegs->size(); j != je; ++j) getReg((*TupRegs)[j]); } // Precompute all sub-register maps now all the registers are known. // This will create Composite entries for all inferred sub-register indices. NumRegUnits = 0; for (unsigned i = 0, e = Registers.size(); i != e; ++i) Registers[i]->getSubRegs(*this); // Read in register class definitions. std::vector<Record*> RCs = Records.getAllDerivedDefinitions("RegisterClass"); if (RCs.empty()) throw std::string("No 'RegisterClass' subclasses defined!"); // Allocate user-defined register classes. RegClasses.reserve(RCs.size()); for (unsigned i = 0, e = RCs.size(); i != e; ++i) addToMaps(new CodeGenRegisterClass(*this, RCs[i])); // Infer missing classes to create a full algebra. computeInferredRegisterClasses(); // Order register classes topologically and assign enum values. array_pod_sort(RegClasses.begin(), RegClasses.end(), TopoOrderRC); for (unsigned i = 0, e = RegClasses.size(); i != e; ++i) RegClasses[i]->EnumValue = i; CodeGenRegisterClass::computeSubClasses(*this); }
// Emits the enumeration list for attributes. void EmitClangAttrList(RecordKeeper &Records, raw_ostream &OS) { OS << "// This file is generated by TableGen. Do not edit.\n\n"; OS << "#ifndef LAST_ATTR\n"; OS << "#define LAST_ATTR(NAME) ATTR(NAME)\n"; OS << "#endif\n\n"; OS << "#ifndef INHERITABLE_ATTR\n"; OS << "#define INHERITABLE_ATTR(NAME) ATTR(NAME)\n"; OS << "#endif\n\n"; OS << "#ifndef LAST_INHERITABLE_ATTR\n"; OS << "#define LAST_INHERITABLE_ATTR(NAME) INHERITABLE_ATTR(NAME)\n"; OS << "#endif\n\n"; OS << "#ifndef INHERITABLE_PARAM_ATTR\n"; OS << "#define INHERITABLE_PARAM_ATTR(NAME) ATTR(NAME)\n"; OS << "#endif\n\n"; OS << "#ifndef LAST_INHERITABLE_PARAM_ATTR\n"; OS << "#define LAST_INHERITABLE_PARAM_ATTR(NAME)" " INHERITABLE_PARAM_ATTR(NAME)\n"; OS << "#endif\n\n"; Record *InhClass = Records.getClass("InheritableAttr"); Record *InhParamClass = Records.getClass("InheritableParamAttr"); std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), NonInhAttrs, InhAttrs, InhParamAttrs; for (std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(); i != e; ++i) { if (!(*i)->getValueAsBit("ASTNode")) continue; if ((*i)->isSubClassOf(InhParamClass)) InhParamAttrs.push_back(*i); else if ((*i)->isSubClassOf(InhClass)) InhAttrs.push_back(*i); else NonInhAttrs.push_back(*i); } EmitAttrList(OS, "INHERITABLE_PARAM_ATTR", InhParamAttrs); EmitAttrList(OS, "INHERITABLE_ATTR", InhAttrs); EmitAttrList(OS, "ATTR", NonInhAttrs); OS << "#undef LAST_ATTR\n"; OS << "#undef INHERITABLE_ATTR\n"; OS << "#undef LAST_INHERITABLE_ATTR\n"; OS << "#undef LAST_INHERITABLE_PARAM_ATTR\n"; OS << "#undef ATTR\n"; }
void clang::EmitClangCommentHTMLTagsProperties(RecordKeeper &Records, raw_ostream &OS) { std::vector<Record *> Tags = Records.getAllDerivedDefinitions("Tag"); std::vector<StringMatcher::StringPair> MatchesEndTagOptional; std::vector<StringMatcher::StringPair> MatchesEndTagForbidden; for (Record *Tag : Tags) { std::string Spelling = Tag->getValueAsString("Spelling"); StringMatcher::StringPair Match(Spelling, "return true;"); if (Tag->getValueAsBit("EndTagOptional")) MatchesEndTagOptional.push_back(Match); if (Tag->getValueAsBit("EndTagForbidden")) MatchesEndTagForbidden.push_back(Match); } emitSourceFileHeader("HTML tag properties", OS); OS << "bool isHTMLEndTagOptional(StringRef Name) {\n"; StringMatcher("Name", MatchesEndTagOptional, OS).Emit(); OS << " return false;\n" << "}\n\n"; OS << "bool isHTMLEndTagForbidden(StringRef Name) {\n"; StringMatcher("Name", MatchesEndTagForbidden, OS).Emit(); OS << " return false;\n" << "}\n\n"; }
// Emits the LateParsed property for attributes. void EmitClangAttrLateParsedList(RecordKeeper &Records, raw_ostream &OS) { OS << "// This file is generated by TableGen. Do not edit.\n\n"; std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"); for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end(); I != E; ++I) { Record &Attr = **I; bool LateParsed = Attr.getValueAsBit("LateParsed"); if (LateParsed) { std::vector<Record*> Spellings = Attr.getValueAsListOfDefs("Spellings"); // FIXME: Handle non-GNU attributes for (std::vector<Record*>::const_iterator I = Spellings.begin(), E = Spellings.end(); I != E; ++I) { if ((*I)->getValueAsString("Variety") != "GNU") continue; OS << ".Case(\"" << (*I)->getValueAsString("Name") << "\", " << LateParsed << ")\n"; } } } }
void EmitClangCommentHTMLNamedCharacterReferences(RecordKeeper &Records, raw_ostream &OS) { std::vector<Record *> Tags = Records.getAllDerivedDefinitions("NCR"); std::vector<StringMatcher::StringPair> NameToUTF8; SmallString<32> CLiteral; for (std::vector<Record *>::iterator I = Tags.begin(), E = Tags.end(); I != E; ++I) { Record &Tag = **I; std::string Spelling = Tag.getValueAsString("Spelling"); uint64_t CodePoint = Tag.getValueAsInt("CodePoint"); CLiteral.clear(); CLiteral.append("return "); if (!translateCodePointToUTF8(CodePoint, CLiteral)) { SrcMgr.PrintMessage(Tag.getLoc().front(), SourceMgr::DK_Error, Twine("invalid code point")); continue; } CLiteral.append(";"); StringMatcher::StringPair Match(Spelling, CLiteral.str()); NameToUTF8.push_back(Match); } emitSourceFileHeader("HTML named character reference to UTF-8 " "translation", OS); OS << "StringRef translateHTMLNamedCharacterReferenceToUTF8(\n" " StringRef Name) {\n"; StringMatcher("Name", NameToUTF8, OS).Emit(); OS << " return StringRef();\n" << "}\n\n"; }
SemanticsTarget::SemanticsTarget(RecordKeeper &Records) : Records(Records), CGPatterns(Records), CGTarget(CGPatterns.getTargetInfo()), SDNodeEquiv(), ConstantIdx() { for (Record *Equiv : Records.getAllDerivedDefinitions("SDNodeEquiv")) SDNodeEquiv[Equiv->getValueAsDef("TargetSpecific")] = Equiv->getValueAsDef("TargetIndependent"); }
static void emitEnums(raw_ostream &OS, RecordKeeper &Records) { std::vector<Record*> InstrMapVec; InstrMapVec = Records.getAllDerivedDefinitions("InstrMapping"); std::map<std::string, std::vector<Init*> > ColFieldValueMap; // Iterate over all InstrMapping records and create a map between column // fields and their possible values across all records. for (unsigned i = 0, e = InstrMapVec.size(); i < e; i++) { Record *CurMap = InstrMapVec[i]; ListInit *ColFields; ColFields = CurMap->getValueAsListInit("ColFields"); ListInit *List = CurMap->getValueAsListInit("ValueCols"); std::vector<ListInit*> ValueCols; unsigned ListSize = List->size(); for (unsigned j = 0; j < ListSize; j++) { ListInit *ListJ = dyn_cast<ListInit>(List->getElement(j)); if (ListJ->size() != ColFields->size()) PrintFatalError("Record `" + CurMap->getName() + "', field " "`ValueCols' entries don't match with the entries in 'ColFields' !"); ValueCols.push_back(ListJ); } for (unsigned j = 0, endCF = ColFields->size(); j < endCF; j++) { for (unsigned k = 0; k < ListSize; k++){ std::string ColName = ColFields->getElement(j)->getAsUnquotedString(); ColFieldValueMap[ColName].push_back((ValueCols[k])->getElement(j)); } } } for (std::map<std::string, std::vector<Init*> >::iterator II = ColFieldValueMap.begin(), IE = ColFieldValueMap.end(); II != IE; II++) { std::vector<Init*> FieldValues = (*II).second; // Delete duplicate entries from ColFieldValueMap for (unsigned i = 0; i < FieldValues.size() - 1; i++) { Init *CurVal = FieldValues[i]; for (unsigned j = i+1; j < FieldValues.size(); j++) { if (CurVal == FieldValues[j]) { FieldValues.erase(FieldValues.begin()+j); } } } // Emit enumerated values for the column fields. OS << "enum " << (*II).first << " {\n"; for (unsigned i = 0, endFV = FieldValues.size(); i < endFV; i++) { OS << "\t" << (*II).first << "_" << FieldValues[i]->getAsUnquotedString(); if (i != endFV - 1) OS << ",\n"; else OS << "\n};\n\n"; } } }
std::vector<CodeGenIntrinsic> llvm::LoadIntrinsics(const RecordKeeper &RC) { std::vector<Record*> I = RC.getAllDerivedDefinitions("Intrinsic"); std::vector<CodeGenIntrinsic> Result; for (unsigned i = 0, e = I.size(); i != e; ++i) Result.push_back(CodeGenIntrinsic(I[i])); return Result; }
// Emits and addendum to a .inc file to enumerate the clang declaration // contexts. void EmitClangDeclContext(RecordKeeper &Records, raw_ostream &OS) { // FIXME: Find a .td file format to allow for this to be represented better. emitSourceFileHeader("List of AST Decl nodes", OS); OS << "#ifndef DECL_CONTEXT\n"; OS << "# define DECL_CONTEXT(DECL)\n"; OS << "#endif\n"; OS << "#ifndef DECL_CONTEXT_BASE\n"; OS << "# define DECL_CONTEXT_BASE(DECL) DECL_CONTEXT(DECL)\n"; OS << "#endif\n"; typedef std::set<Record*> RecordSet; typedef std::vector<Record*> RecordVector; RecordVector DeclContextsVector = Records.getAllDerivedDefinitions("DeclContext"); RecordVector Decls = Records.getAllDerivedDefinitions("Decl"); RecordSet DeclContexts (DeclContextsVector.begin(), DeclContextsVector.end()); for (RecordVector::iterator i = Decls.begin(), e = Decls.end(); i != e; ++i) { Record *R = *i; if (R->getValue("Base")) { Record *B = R->getValueAsDef("Base"); if (DeclContexts.find(B) != DeclContexts.end()) { OS << "DECL_CONTEXT_BASE(" << B->getName() << ")\n"; DeclContexts.erase(B); } } } // To keep identical order, RecordVector may be used // instead of RecordSet. for (RecordVector::iterator i = DeclContextsVector.begin(), e = DeclContextsVector.end(); i != e; ++i) if (DeclContexts.find(*i) != DeclContexts.end()) OS << "DECL_CONTEXT(" << (*i)->getName() << ")\n"; OS << "#undef DECL_CONTEXT\n"; OS << "#undef DECL_CONTEXT_BASE\n"; }
// Emits the code to read an attribute from a precompiled header. void EmitClangAttrPCHRead(RecordKeeper &Records, raw_ostream &OS) { OS << "// This file is generated by TableGen. Do not edit.\n\n"; Record *InhClass = Records.getClass("InheritableAttr"); std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), ArgRecords; std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ai, ae; std::vector<Argument*> Args; std::vector<Argument*>::iterator ri, re; OS << " switch (Kind) {\n"; OS << " default:\n"; OS << " assert(0 && \"Unknown attribute!\");\n"; OS << " break;\n"; for (; i != e; ++i) { Record &R = **i; if (!R.getValueAsBit("ASTNode")) continue; OS << " case attr::" << R.getName() << ": {\n"; if (R.isSubClassOf(InhClass)) OS << " bool isInherited = Record[Idx++];\n"; ArgRecords = R.getValueAsListOfDefs("Args"); Args.clear(); for (ai = ArgRecords.begin(), ae = ArgRecords.end(); ai != ae; ++ai) { Argument *A = createArgument(**ai, R.getName()); Args.push_back(A); A->writePCHReadDecls(OS); } OS << " New = new (Context) " << R.getName() << "Attr(Range, Context"; for (ri = Args.begin(), re = Args.end(); ri != re; ++ri) { OS << ", "; (*ri)->writePCHReadArgs(OS); } OS << ");\n"; if (R.isSubClassOf(InhClass)) OS << " cast<InheritableAttr>(New)->setInherited(isInherited);\n"; OS << " break;\n"; OS << " }\n"; } OS << " }\n"; }
void EmitClangDataCollectors(RecordKeeper &RK, raw_ostream &OS) { const auto &Defs = RK.getClasses(); for (const auto &Entry : Defs) { Record &R = *Entry.second; OS << "DEF_ADD_DATA(" << R.getName() << ", {\n"; auto Code = R.getValue("Code")->getValue(); OS << Code->getAsUnquotedString() << "}\n)"; OS << "\n"; } OS << "#undef DEF_ADD_DATA\n"; }
void EmitClangCommentCommandInfo(RecordKeeper &Records, raw_ostream &OS) { emitSourceFileHeader("A list of commands useable in documentation " "comments", OS); OS << "namespace {\n" "const CommandInfo Commands[] = {\n"; std::vector<Record *> Tags = Records.getAllDerivedDefinitions("Command"); for (size_t i = 0, e = Tags.size(); i != e; ++i) { Record &Tag = *Tags[i]; OS << " { " << "\"" << Tag.getValueAsString("Name") << "\", " << "\"" << Tag.getValueAsString("EndCommandName") << "\", " << i << ", " << Tag.getValueAsInt("NumArgs") << ", " << Tag.getValueAsBit("IsInlineCommand") << ", " << Tag.getValueAsBit("IsBlockCommand") << ", " << Tag.getValueAsBit("IsBriefCommand") << ", " << Tag.getValueAsBit("IsReturnsCommand") << ", " << Tag.getValueAsBit("IsParamCommand") << ", " << Tag.getValueAsBit("IsTParamCommand") << ", " << Tag.getValueAsBit("IsDeprecatedCommand") << ", " << Tag.getValueAsBit("IsHeaderfileCommand") << ", " << Tag.getValueAsBit("IsEmptyParagraphAllowed") << ", " << Tag.getValueAsBit("IsVerbatimBlockCommand") << ", " << Tag.getValueAsBit("IsVerbatimBlockEndCommand") << ", " << Tag.getValueAsBit("IsVerbatimLineCommand") << ", " << Tag.getValueAsBit("IsDeclarationCommand") << ", " << Tag.getValueAsBit("IsFunctionDeclarationCommand") << ", " << Tag.getValueAsBit("IsRecordLikeDetailCommand") << ", " << Tag.getValueAsBit("IsRecordLikeDeclarationCommand") << ", " << /* IsUnknownCommand = */ "0" << " }"; if (i + 1 != e) OS << ","; OS << "\n"; } OS << "};\n" "} // unnamed namespace\n\n"; std::vector<StringMatcher::StringPair> Matches; for (size_t i = 0, e = Tags.size(); i != e; ++i) { Record &Tag = *Tags[i]; std::string Name = Tag.getValueAsString("Name"); std::string Return; raw_string_ostream(Return) << "return &Commands[" << i << "];"; Matches.push_back(StringMatcher::StringPair(Name, Return)); } OS << "const CommandInfo *CommandTraits::getBuiltinCommandInfo(\n" << " StringRef Name) {\n"; StringMatcher("Name", Matches, OS).Emit(); OS << " return NULL;\n" << "}\n\n"; }
std::vector<CodeGenIntrinsic> llvm::LoadIntrinsics(const RecordKeeper &RC, bool TargetOnly) { std::vector<Record*> I = RC.getAllDerivedDefinitions("Intrinsic"); std::vector<CodeGenIntrinsic> Result; for (unsigned i = 0, e = I.size(); i != e; ++i) { bool isTarget = I[i]->getValueAsBit("isTarget"); if (isTarget == TargetOnly) Result.push_back(CodeGenIntrinsic(I[i])); } return Result; }
// Emits the class method definitions for attributes. void EmitClangAttrImpl(RecordKeeper &Records, raw_ostream &OS) { OS << "// This file is generated by TableGen. Do not edit.\n\n"; std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"); std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ri, re; std::vector<Argument*>::iterator ai, ae; for (; i != e; ++i) { Record &R = **i; if (!R.getValueAsBit("ASTNode")) continue; std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args"); std::vector<Record*> Spellings = R.getValueAsListOfDefs("Spellings"); std::vector<Argument*> Args; for (ri = ArgRecords.begin(), re = ArgRecords.end(); ri != re; ++ri) Args.push_back(createArgument(**ri, R.getName())); for (ai = Args.begin(), ae = Args.end(); ai != ae; ++ai) (*ai)->writeAccessorDefinitions(OS); OS << R.getName() << "Attr *" << R.getName() << "Attr::clone(ASTContext &C) const {\n"; OS << " return new (C) " << R.getName() << "Attr(getLocation(), C"; for (ai = Args.begin(); ai != ae; ++ai) { OS << ", "; (*ai)->writeCloneArgs(OS); } OS << ");\n}\n\n"; OS << "void " << R.getName() << "Attr::printPretty(" << "llvm::raw_ostream &OS, ASTContext &Ctx) const {\n"; if (Spellings.begin() != Spellings.end()) { StringRef Spelling = (*Spellings.begin())->getValueAsString("Name"); OS << " OS << \" __attribute__((" << Spelling; if (Args.size()) OS << "("; if (Spelling == "availability") { writeAvailabilityValue(OS); } else { for (ai = Args.begin(); ai != ae; ++ai) { if (ai!=Args.begin()) OS <<", "; (*ai)->writeValue(OS); } } if (Args.size()) OS << ")"; OS << "))\";\n"; } OS << "}\n\n"; } }
// Emits the kind list of parsed attributes void EmitClangAttrParsedAttrKinds(RecordKeeper &Records, raw_ostream &OS) { OS << "// This file is generated by TableGen. Do not edit.\n\n"; OS << "\n"; std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"); std::vector<StringMatcher::StringPair> Matches; for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end(); I != E; ++I) { Record &Attr = **I; bool SemaHandler = Attr.getValueAsBit("SemaHandler"); bool Ignored = Attr.getValueAsBit("Ignored"); bool DistinctSpellings = Attr.getValueAsBit("DistinctSpellings"); if (SemaHandler || Ignored) { std::vector<Record*> Spellings = Attr.getValueAsListOfDefs("Spellings"); for (std::vector<Record*>::const_iterator I = Spellings.begin(), E = Spellings.end(); I != E; ++I) { std::string RawSpelling = (*I)->getValueAsString("Name"); StringRef AttrName = NormalizeAttrName(DistinctSpellings ? StringRef(RawSpelling) : StringRef(Attr.getName())); SmallString<64> Spelling; if ((*I)->getValueAsString("Variety") == "CXX11") { Spelling += (*I)->getValueAsString("Namespace"); Spelling += "::"; } Spelling += NormalizeAttrSpelling(RawSpelling); if (SemaHandler) Matches.push_back( StringMatcher::StringPair( StringRef(Spelling), "return AttributeList::AT_" + AttrName.str() + ";")); else Matches.push_back( StringMatcher::StringPair( StringRef(Spelling), "return AttributeList::IgnoredAttribute;")); } } } OS << "static AttributeList::Kind getAttrKind(StringRef Name) {\n"; StringMatcher("Name", Matches, OS).Emit(); OS << "return AttributeList::UnknownAttribute;\n" << "}\n"; }
void EmitClangDiagGroups(RecordKeeper &Records, raw_ostream &OS) { // Compute a mapping from a DiagGroup to all of its parents. DiagGroupParentMap DGParentMap(Records); std::vector<Record *> Diags = Records.getAllDerivedDefinitions("Diagnostic"); std::vector<Record *> DiagGroups = Records.getAllDerivedDefinitions("DiagGroup"); std::map<std::string, GroupInfo> DiagsInGroup; groupDiagnostics(Diags, DiagGroups, DiagsInGroup); // All extensions are implicitly in the "pedantic" group. Record the // implicit set of groups in the "pedantic" group, and use this information // later when emitting the group information for Pedantic. RecordVec DiagsInPedantic; RecordVec GroupsInPedantic; InferPedantic inferPedantic(DGParentMap, Diags, DiagGroups, DiagsInGroup); inferPedantic.compute(&DiagsInPedantic, &GroupsInPedantic); StringToOffsetTable GroupNames; for (std::map<std::string, GroupInfo>::const_iterator I = DiagsInGroup.begin(), E = DiagsInGroup.end(); I != E; ++I) { // Store a pascal-style length byte at the beginning of the string. std::string Name = char(I->first.size()) + I->first; GroupNames.GetOrAddStringOffset(Name, false); } emitAllDiagArrays(DiagsInGroup, DiagsInPedantic, GroupsInPedantic, GroupNames, OS); emitDiagTable(DiagsInGroup, DiagsInPedantic, GroupsInPedantic, GroupNames, OS); emitCategoryTable(Records, OS); }
void clang::EmitClangCommentHTMLTags(RecordKeeper &Records, raw_ostream &OS) { std::vector<Record *> Tags = Records.getAllDerivedDefinitions("Tag"); std::vector<StringMatcher::StringPair> Matches; for (Record *Tag : Tags) { std::string Spelling = Tag->getValueAsString("Spelling"); Matches.push_back(StringMatcher::StringPair(Spelling, "return true;")); } emitSourceFileHeader("HTML tag name matcher", OS); OS << "bool isHTMLTagName(StringRef Name) {\n"; StringMatcher("Name", Matches, OS).Emit(); OS << " return false;\n" << "}\n\n"; }
void EmitClangCommentCommandList(RecordKeeper &Records, raw_ostream &OS) { emitSourceFileHeader("A list of commands useable in documentation " "comments", OS); OS << "#ifndef COMMENT_COMMAND\n" << "# define COMMENT_COMMAND(NAME)\n" << "#endif\n"; std::vector<Record *> Tags = Records.getAllDerivedDefinitions("Command"); for (size_t i = 0, e = Tags.size(); i != e; ++i) { Record &Tag = *Tags[i]; std::string MangledName = MangleName(Tag.getValueAsString("Name")); OS << "COMMENT_COMMAND(" << MangledName << ")\n"; } }
// Emits the list of spellings for attributes. void EmitClangAttrSpellingList(RecordKeeper &Records, raw_ostream &OS) { OS << "// This file is generated by TableGen. Do not edit.\n\n"; std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"); for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end(); I != E; ++I) { Record &Attr = **I; std::vector<Record*> Spellings = Attr.getValueAsListOfDefs("Spellings"); for (std::vector<Record*>::const_iterator I = Spellings.begin(), E = Spellings.end(); I != E; ++I) { OS << ".Case(\"" << (*I)->getValueAsString("Name") << "\", true)\n"; } } }
std::vector<CodeGenIntrinsic> llvm::LoadIntrinsics(const RecordKeeper &RC) { std::vector<Record*> I = RC.getAllDerivedDefinitions("Intrinsic"); std::vector<CodeGenIntrinsic> Result; // If we are in the context of a target .td file, get the target info so that // we can decode the current intptr_t. CodeGenTarget *CGT = 0; if (Records.getClass("Target") && Records.getAllDerivedDefinitions("Target").size() == 1) CGT = new CodeGenTarget(); for (unsigned i = 0, e = I.size(); i != e; ++i) Result.push_back(CodeGenIntrinsic(I[i], CGT)); delete CGT; return Result; }
std::vector<CodeGenIntrinsic> llvm::LoadIntrinsics(const RecordKeeper &RC, bool TargetOnly) { std::vector<Record*> I = RC.getAllDerivedDefinitions("Intrinsic"); std::vector<CodeGenIntrinsic> Result; Result.reserve(I.size()); for (unsigned i = 0, e = I.size(); i != e; ++i) { bool isTarget = I[i]->getValueAsBit("isTarget"); if (isTarget == TargetOnly) Result.push_back(CodeGenIntrinsic(I[i])); } std::sort(Result.begin(), Result.end(), [](const CodeGenIntrinsic& LHS, const CodeGenIntrinsic& RHS) { return LHS.Name < RHS.Name; }); return Result; }
bool emit(raw_ostream& os, RecordKeeper& records) { os << "module ldc.gccbuiltins_"; os << arch; os << "; \n\nimport core.simd;\n\n"; map<string, Record*> defs = records.getDefs(); for( map<string, Record* >::iterator it = defs.begin(); it != defs.end(); it++) { processRecord(os, *(*it).second, arch); } return false; }
void EmitClangDiagsIndexName(RecordKeeper &Records, raw_ostream &OS) { const std::vector<Record*> &Diags = Records.getAllDerivedDefinitions("Diagnostic"); std::vector<RecordIndexElement> Index; Index.reserve(Diags.size()); for (unsigned i = 0, e = Diags.size(); i != e; ++i) { const Record &R = *(Diags[i]); Index.push_back(RecordIndexElement(R)); } std::sort(Index.begin(), Index.end(), RecordIndexElementSorter()); for (unsigned i = 0, e = Index.size(); i != e; ++i) { const RecordIndexElement &R = Index[i]; OS << "DIAG_NAME_INDEX(" << R.Name << ")\n"; } }
std::vector<std::pair<Record *, SubtargetFeatureInfo>> SubtargetFeatureInfo::getAll(const RecordKeeper &Records) { std::vector<std::pair<Record *, SubtargetFeatureInfo>> SubtargetFeatures; std::vector<Record *> AllPredicates = Records.getAllDerivedDefinitions("Predicate"); for (Record *Pred : AllPredicates) { // Ignore predicates that are not intended for the assembler. // // The "AssemblerMatcherPredicate" string should be promoted to an argument // if we re-use the machinery for non-assembler purposes in future. if (!Pred->getValueAsBit("AssemblerMatcherPredicate")) continue; if (Pred->getName().empty()) PrintFatalError(Pred->getLoc(), "Predicate has no name!"); SubtargetFeatures.emplace_back( Pred, SubtargetFeatureInfo(Pred, SubtargetFeatures.size())); } return SubtargetFeatures; }
//===----------------------------------------------------------------------===// // Parse 'InstrMapping' records and use the information to form relationship // between instructions. These relations are emitted as a tables along with the // functions to query them. //===----------------------------------------------------------------------===// void EmitMapTable(RecordKeeper &Records, raw_ostream &OS) { CodeGenTarget Target(Records); std::string TargetName = Target.getName(); std::vector<Record*> InstrMapVec; InstrMapVec = Records.getAllDerivedDefinitions("InstrMapping"); if (InstrMapVec.empty()) return; OS << "#ifdef GET_INSTRMAP_INFO\n"; OS << "#undef GET_INSTRMAP_INFO\n"; OS << "namespace llvm {\n\n"; OS << "namespace " << TargetName << " {\n\n"; // Emit coulumn field names and their values as enums. emitEnums(OS, Records); // Iterate over all instruction mapping records and construct relationship // maps based on the information specified there. // for (Record *CurMap : InstrMapVec) { MapTableEmitter IMap(Target, Records, CurMap); // Build RowInstrMap to group instructions based on their values for // RowFields. In the process, also collect key instructions into // KeyInstrVec. IMap.buildRowInstrMap(); // Build MapTable to map key instructions with the corresponding column // instructions. IMap.buildMapTable(); // Emit map tables and the functions to query them. IMap.emitTablesWithFunc(OS); } OS << "} // End " << TargetName << " namespace\n"; OS << "} // End llvm namespace\n"; OS << "#endif // GET_INSTRMAP_INFO\n\n"; }
CodeGenIntrinsicTable::CodeGenIntrinsicTable(const RecordKeeper &RC, bool TargetOnly) { std::vector<Record*> Defs = RC.getAllDerivedDefinitions("Intrinsic"); Intrinsics.reserve(Defs.size()); for (unsigned I = 0, e = Defs.size(); I != e; ++I) { bool isTarget = Defs[I]->getValueAsBit("isTarget"); if (isTarget == TargetOnly) Intrinsics.push_back(CodeGenIntrinsic(Defs[I])); } std::sort(Intrinsics.begin(), Intrinsics.end(), [](const CodeGenIntrinsic &LHS, const CodeGenIntrinsic &RHS) { return std::tie(LHS.TargetPrefix, LHS.Name) < std::tie(RHS.TargetPrefix, RHS.Name); }); Targets.push_back({"", 0, 0}); for (size_t I = 0, E = Intrinsics.size(); I < E; ++I) if (Intrinsics[I].TargetPrefix != Targets.back().Name) { Targets.back().Count = I - Targets.back().Offset; Targets.push_back({Intrinsics[I].TargetPrefix, I, 0}); } Targets.back().Count = Intrinsics.size() - Targets.back().Offset; }
// Emits the list of parsed attributes. void EmitClangAttrParsedAttrList(RecordKeeper &Records, raw_ostream &OS) { OS << "// This file is generated by TableGen. Do not edit.\n\n"; OS << "#ifndef PARSED_ATTR\n"; OS << "#define PARSED_ATTR(NAME) NAME\n"; OS << "#endif\n\n"; std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"); for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end(); I != E; ++I) { Record &Attr = **I; bool SemaHandler = Attr.getValueAsBit("SemaHandler"); bool DistinctSpellings = Attr.getValueAsBit("DistinctSpellings"); if (SemaHandler) { if (DistinctSpellings) { std::vector<Record*> Spellings = Attr.getValueAsListOfDefs("Spellings"); for (std::vector<Record*>::const_iterator I = Spellings.begin(), E = Spellings.end(); I != E; ++I) { std::string AttrName = (*I)->getValueAsString("Name"); StringRef Spelling = NormalizeAttrName(AttrName); OS << "PARSED_ATTR(" << Spelling << ")\n"; } } else { StringRef AttrName = Attr.getName(); AttrName = NormalizeAttrName(AttrName); OS << "PARSED_ATTR(" << AttrName << ")\n"; } } } }
void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) { // Get the option groups and options. const std::vector<Record*> &Groups = Records.getAllDerivedDefinitions("OptionGroup"); std::vector<Record*> Opts = Records.getAllDerivedDefinitions("Option"); emitSourceFileHeader("Option Parsing Definitions", OS); array_pod_sort(Opts.begin(), Opts.end(), CompareOptionRecords); // Generate prefix groups. typedef SmallVector<SmallString<2>, 2> PrefixKeyT; typedef std::map<PrefixKeyT, std::string> PrefixesT; PrefixesT Prefixes; Prefixes.insert(std::make_pair(PrefixKeyT(), "prefix_0")); unsigned CurPrefix = 0; for (unsigned i = 0, e = Opts.size(); i != e; ++i) { const Record &R = *Opts[i]; std::vector<std::string> prf = R.getValueAsListOfStrings("Prefixes"); PrefixKeyT prfkey(prf.begin(), prf.end()); unsigned NewPrefix = CurPrefix + 1; if (Prefixes.insert(std::make_pair(prfkey, (Twine("prefix_") + Twine(NewPrefix)).str())).second) CurPrefix = NewPrefix; } // Dump prefixes. OS << "/////////\n"; OS << "// Prefixes\n\n"; OS << "#ifdef PREFIX\n"; OS << "#define COMMA ,\n"; for (PrefixesT::const_iterator I = Prefixes.begin(), E = Prefixes.end(); I != E; ++I) { OS << "PREFIX("; // Prefix name. OS << I->second; // Prefix values. OS << ", {"; for (PrefixKeyT::const_iterator PI = I->first.begin(), PE = I->first.end(); PI != PE; ++PI) { OS << "\"" << *PI << "\" COMMA "; } OS << "0})\n"; } OS << "#undef COMMA\n"; OS << "#endif\n\n"; OS << "/////////\n"; OS << "// Groups\n\n"; OS << "#ifdef OPTION\n"; for (unsigned i = 0, e = Groups.size(); i != e; ++i) { const Record &R = *Groups[i]; // Start a single option entry. OS << "OPTION("; // The option prefix; OS << "0"; // The option string. OS << ", \"" << R.getValueAsString("Name") << '"'; // The option identifier name. OS << ", "<< getOptionName(R); // The option kind. OS << ", Group"; // The containing option group (if any). OS << ", "; if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group"))) OS << getOptionName(*DI->getDef()); else OS << "INVALID"; // The other option arguments (unused for groups). OS << ", INVALID, 0, 0, 0"; // The option help text. if (!isa<UnsetInit>(R.getValueInit("HelpText"))) { OS << ",\n"; OS << " "; write_cstring(OS, R.getValueAsString("HelpText")); } else OS << ", 0"; // The option meta-variable name (unused). OS << ", 0)\n"; } OS << "\n"; OS << "//////////\n"; OS << "// Options\n\n"; for (unsigned i = 0, e = Opts.size(); i != e; ++i) { const Record &R = *Opts[i]; // Start a single option entry. OS << "OPTION("; // The option prefix; std::vector<std::string> prf = R.getValueAsListOfStrings("Prefixes"); OS << Prefixes[PrefixKeyT(prf.begin(), prf.end())] << ", "; // The option string. write_cstring(OS, R.getValueAsString("Name")); // The option identifier name. OS << ", "<< getOptionName(R); // The option kind. OS << ", " << R.getValueAsDef("Kind")->getValueAsString("Name"); // The containing option group (if any). OS << ", "; if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group"))) OS << getOptionName(*DI->getDef()); else OS << "INVALID"; // The option alias (if any). OS << ", "; if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Alias"))) OS << getOptionName(*DI->getDef()); else OS << "INVALID"; // The option alias arguments (if any). // Emitted as a \0 separated list in a string, e.g. ["foo", "bar"] // would become "foo\0bar\0". Note that the compiler adds an implicit // terminating \0 at the end. OS << ", "; std::vector<std::string> AliasArgs = R.getValueAsListOfStrings("AliasArgs"); if (AliasArgs.size() == 0) { OS << "0"; } else { OS << "\""; for (size_t i = 0, e = AliasArgs.size(); i != e; ++i) OS << AliasArgs[i] << "\\0"; OS << "\""; } // The option flags. const ListInit *LI = R.getValueAsListInit("Flags"); if (LI->empty()) { OS << ", 0"; } else { OS << ", "; for (unsigned i = 0, e = LI->size(); i != e; ++i) { if (i) OS << " | "; OS << cast<DefInit>(LI->getElement(i))->getDef()->getName(); } } // The option parameter field. OS << ", " << R.getValueAsInt("NumArgs"); // The option help text. if (!isa<UnsetInit>(R.getValueInit("HelpText"))) { OS << ",\n"; OS << " "; write_cstring(OS, R.getValueAsString("HelpText")); } else OS << ", 0"; // The option meta-variable name. OS << ", "; if (!isa<UnsetInit>(R.getValueInit("MetaVarName"))) write_cstring(OS, R.getValueAsString("MetaVarName")); else OS << "0"; OS << ")\n"; } OS << "#endif\n"; }
int main(int argc, char **argv) { RecordKeeper Records; sys::PrintStackTraceOnErrorSignal(); PrettyStackTraceProgram X(argc, argv); cl::ParseCommandLineOptions(argc, argv); try { // Parse the input file. OwningPtr<MemoryBuffer> File; if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFilename.c_str(), File)) { errs() << "Could not open input file '" << InputFilename << "': " << ec.message() <<"\n"; return 1; } MemoryBuffer *F = File.take(); // Tell SrcMgr about this buffer, which is what TGParser will pick up. SrcMgr.AddNewSourceBuffer(F, SMLoc()); // Record the location of the include directory so that the lexer can find // it later. SrcMgr.setIncludeDirs(IncludeDirs); TGParser Parser(SrcMgr, Records); if (Parser.ParseFile()) return 1; std::string Error; tool_output_file Out(OutputFilename.c_str(), Error); if (!Error.empty()) { errs() << argv[0] << ": error opening " << OutputFilename << ":" << Error << "\n"; return 1; } if (!DependFilename.empty()) { if (OutputFilename == "-") { errs() << argv[0] << ": the option -d must be used together with -o\n"; return 1; } tool_output_file DepOut(DependFilename.c_str(), Error); if (!Error.empty()) { errs() << argv[0] << ": error opening " << DependFilename << ":" << Error << "\n"; return 1; } DepOut.os() << DependFilename << ":"; const std::vector<std::string> &Dependencies = Parser.getDependencies(); for (std::vector<std::string>::const_iterator I = Dependencies.begin(), E = Dependencies.end(); I != E; ++I) { DepOut.os() << " " << (*I); } DepOut.os() << "\n"; DepOut.keep(); } switch (Action) { case PrintRecords: Out.os() << Records; // No argument, dump all contents break; case GenEmitter: CodeEmitterGen(Records).run(Out.os()); break; case GenRegisterEnums: RegisterInfoEmitter(Records).runEnums(Out.os()); break; case GenRegister: RegisterInfoEmitter(Records).run(Out.os()); break; case GenRegisterHeader: RegisterInfoEmitter(Records).runHeader(Out.os()); break; case GenInstrEnums: InstrEnumEmitter(Records).run(Out.os()); break; case GenInstrs: InstrInfoEmitter(Records).run(Out.os()); break; case GenCallingConv: CallingConvEmitter(Records).run(Out.os()); break; case GenAsmWriter: AsmWriterEmitter(Records).run(Out.os()); break; case GenARMDecoder: ARMDecoderEmitter(Records).run(Out.os()); break; case GenAsmMatcher: AsmMatcherEmitter(Records).run(Out.os()); break; case GenClangAttrClasses: ClangAttrClassEmitter(Records).run(Out.os()); break; case GenClangAttrImpl: ClangAttrImplEmitter(Records).run(Out.os()); break; case GenClangAttrList: ClangAttrListEmitter(Records).run(Out.os()); break; case GenClangAttrPCHRead: ClangAttrPCHReadEmitter(Records).run(Out.os()); break; case GenClangAttrPCHWrite: ClangAttrPCHWriteEmitter(Records).run(Out.os()); break; case GenClangAttrSpellingList: ClangAttrSpellingListEmitter(Records).run(Out.os()); break; case GenClangDiagsDefs: ClangDiagsDefsEmitter(Records, ClangComponent).run(Out.os()); break; case GenClangDiagGroups: ClangDiagGroupsEmitter(Records).run(Out.os()); break; case GenClangDiagsIndexName: ClangDiagsIndexNameEmitter(Records).run(Out.os()); break; case GenClangDeclNodes: ClangASTNodesEmitter(Records, "Decl", "Decl").run(Out.os()); ClangDeclContextEmitter(Records).run(Out.os()); break; case GenClangStmtNodes: ClangASTNodesEmitter(Records, "Stmt", "").run(Out.os()); break; case GenClangSACheckers: ClangSACheckersEmitter(Records).run(Out.os()); break; case GenDisassembler: DisassemblerEmitter(Records).run(Out.os()); break; case GenOptParserDefs: OptParserEmitter(Records, true).run(Out.os()); break; case GenOptParserImpl: OptParserEmitter(Records, false).run(Out.os()); break; case GenDAGISel: DAGISelEmitter(Records).run(Out.os()); break; case GenFastISel: FastISelEmitter(Records).run(Out.os()); break; case GenSubtarget: SubtargetEmitter(Records).run(Out.os()); break; case GenIntrinsic: IntrinsicEmitter(Records).run(Out.os()); break; case GenTgtIntrinsic: IntrinsicEmitter(Records, true).run(Out.os()); break; case GenLLVMCConf: LLVMCConfigurationEmitter(Records).run(Out.os()); break; case GenEDInfo: EDEmitter(Records).run(Out.os()); break; case GenArmNeon: NeonEmitter(Records).run(Out.os()); break; case GenArmNeonSema: NeonEmitter(Records).runHeader(Out.os()); break; case GenArmNeonTest: NeonEmitter(Records).runTests(Out.os()); break; case PrintEnums: { std::vector<Record*> Recs = Records.getAllDerivedDefinitions(Class); for (unsigned i = 0, e = Recs.size(); i != e; ++i) Out.os() << Recs[i]->getName() << ", "; Out.os() << "\n"; break; } case PrintSets: { SetTheory Sets; Sets.addFieldExpander("Set", "Elements"); std::vector<Record*> Recs = Records.getAllDerivedDefinitions("Set"); for (unsigned i = 0, e = Recs.size(); i != e; ++i) { Out.os() << Recs[i]->getName() << " = ["; const std::vector<Record*> *Elts = Sets.expand(Recs[i]); assert(Elts && "Couldn't expand Set instance"); for (unsigned ei = 0, ee = Elts->size(); ei != ee; ++ei) Out.os() << ' ' << (*Elts)[ei]->getName(); Out.os() << " ]\n"; } break; } default: assert(1 && "Invalid Action"); return 1; } // Declare success. Out.keep(); return 0; } catch (const TGError &Error) { errs() << argv[0] << ": error:\n"; PrintError(Error.getLoc(), Error.getMessage()); } catch (const std::string &Error) { errs() << argv[0] << ": " << Error << "\n"; } catch (const char *Error) { errs() << argv[0] << ": " << Error << "\n"; } catch (...) { errs() << argv[0] << ": Unknown unexpected exception occurred.\n"; } return 1; }