Index: include/llvm/Analysis/InlineCost.h =================================================================== --- include/llvm/Analysis/InlineCost.h +++ include/llvm/Analysis/InlineCost.h @@ -134,6 +134,9 @@ // adding a replacement API. InlineCost getInlineCost(CallSite CS, Function *Callee, int Threshold); + bool hasCompatibleFnAttrs(const Function &Caller, + const Function &Callee) const; + /// \brief Minimal filter to detect invalid constructs for inlining. bool isInlineViable(Function &Callee); }; Index: include/llvm/Analysis/TargetTransformInfo.h =================================================================== --- include/llvm/Analysis/TargetTransformInfo.h +++ include/llvm/Analysis/TargetTransformInfo.h @@ -763,6 +763,8 @@ class TargetIRAnalysis { public: typedef TargetTransformInfo Result; + typedef std::function + FnAttrsCheckerTy; /// \brief Opaque, unique identifier for this analysis pass. static void *ID() { return (void *)&PassID; } @@ -780,7 +782,8 @@ /// /// The callback will be called with a particular function for which the TTI /// is needed and must return a TTI object for that function. - TargetIRAnalysis(std::function TTICallback); + TargetIRAnalysis(std::function TTICallback, + FnAttrsCheckerTy FnAttrsChecker); // Value semantics. We spell out the constructors for MSVC. TargetIRAnalysis(const TargetIRAnalysis &Arg) @@ -798,6 +801,9 @@ Result run(Function &F); + bool hasCompatibleFnAttrs(const Function &Caller, + const Function &Callee) const; + private: static char PassID; @@ -815,6 +821,8 @@ /// \brief Helper function used as the callback in the default constructor. static Result getDefaultTTI(Function &F); + + FnAttrsCheckerTy FnAttrsChecker; }; /// \brief Wrapper pass for TargetTransformInfo. @@ -839,6 +847,9 @@ explicit TargetTransformInfoWrapperPass(TargetIRAnalysis TIRA); TargetTransformInfo &getTTI(Function &F); + + bool hasCompatibleFnAttrs(const Function &Caller, + const Function &Callee) const; }; /// \brief Create an analysis pass wrapper around a TTI object. Index: include/llvm/IR/Attributes.h =================================================================== --- include/llvm/IR/Attributes.h +++ include/llvm/IR/Attributes.h @@ -33,6 +33,7 @@ class AttributeSetNode; class Constant; template struct DenseMapInfo; +class Function; class LLVMContext; class Type; @@ -64,55 +65,7 @@ enum AttrKind { // IR-Level Attributes None, ///< No attributes have been set - Alignment, ///< Alignment of parameter (5 bits) - ///< stored as log2 of alignment with +1 bias - ///< 0 means unaligned (different from align(1)) - AlwaysInline, ///< inline=always - Builtin, ///< Callee is recognized as a builtin, despite - ///< nobuiltin attribute on its declaration. - ByVal, ///< Pass structure by value - InAlloca, ///< Pass structure in an alloca - Cold, ///< Marks function as being in a cold path. - InlineHint, ///< Source said inlining was desirable - InReg, ///< Force argument to be passed in register - JumpTable, ///< Build jump-instruction tables and replace refs. - MinSize, ///< Function must be optimized for size first - Naked, ///< Naked function - Nest, ///< Nested function static chain - NoAlias, ///< Considered to not alias after call - NoBuiltin, ///< Callee isn't recognized as a builtin - NoCapture, ///< Function creates no aliases of pointer - NoDuplicate, ///< Call cannot be duplicated - NoImplicitFloat, ///< Disable implicit floating point insts - NoInline, ///< inline=never - NonLazyBind, ///< Function is called early and/or - ///< often, so lazy binding isn't worthwhile - NonNull, ///< Pointer is known to be not null - Dereferenceable, ///< Pointer is known to be dereferenceable - NoRedZone, ///< Disable redzone - NoReturn, ///< Mark the function as not returning - NoUnwind, ///< Function doesn't unwind stack - OptimizeForSize, ///< opt_size - OptimizeNone, ///< Function must not be optimized. - ReadNone, ///< Function does not access memory - ReadOnly, ///< Function only reads from memory - Returned, ///< Return value is always equal to this argument - ReturnsTwice, ///< Function can return twice - SExt, ///< Sign extended before/after call - StackAlignment, ///< Alignment of stack for function (3 bits) - ///< stored as log2 of alignment with +1 bias 0 - ///< means unaligned (different from - ///< alignstack=(1)) - StackProtect, ///< Stack protection. - StackProtectReq, ///< Stack protection required. - StackProtectStrong, ///< Strong Stack protection. - StructRet, ///< Hidden pointer to structure to return - SanitizeAddress, ///< AddressSanitizer is on. - SanitizeThread, ///< ThreadSanitizer is on. - SanitizeMemory, ///< MemorySanitizer is on. - UWTable, ///< Function must be in a unwind table - ZExt, ///< Zero extended before/after call - + #include "llvm/IR/FunctionAttrEnum.inc" EndAttrKinds ///< Sentinal value useful for loops }; private: @@ -528,6 +481,8 @@ /// \brief Which attributes cannot be applied to a type. AttributeSet typeIncompatible(Type *Ty, uint64_t Index); +bool hasCompatibleFnAttrs(const Function &Caller, const Function &Callee); + } // end AttributeFuncs namespace } // end llvm namespace Index: include/llvm/IR/EnumAttributes.td =================================================================== --- /dev/null +++ include/llvm/IR/EnumAttributes.td @@ -0,0 +1,55 @@ + +class CompatCheckBase { + bit Val; + let Val = V; +} + +def DontCheckCompat : CompatCheckBase<0>; +def CheckCompat : CompatCheckBase<1>; + +class Attr { + bit CheckCompat; + let CheckCompat = B.Val; +} + +def Alignment : Attr; +def AlwaysInline : Attr; +def Builtin : Attr; +def ByVal : Attr; +def InAlloca : Attr; +def Cold : Attr; +def InlineHint : Attr; +def InReg : Attr; +def JumpTable : Attr; +def MinSize : Attr; +def Naked : Attr; +def Nest : Attr; +def NoAlias : Attr; +def NoBuiltin : Attr; +def NoCapture : Attr; +def NoDuplicate : Attr; +def NoImplicitFloat : Attr; +def NoInline : Attr; +def NonLazyBind : Attr; +def NonNull : Attr; +def Dereferenceable : Attr; +def NoRedZone : Attr; +def NoReturn : Attr; +def NoUnwind : Attr; +def OptimizeForSize : Attr; +def OptimizeNone : Attr; +def ReadNone : Attr; +def ReadOnly : Attr; +def Returned : Attr; +def ReturnsTwice : Attr; +def SExt : Attr; +def StackAlignment : Attr; +def StackProtect : Attr; +def StackProtectReq : Attr; +def StackProtectStrong : Attr; +def StructRet : Attr; +def SanitizeAddress : Attr; +def SanitizeThread : Attr; +def SanitizeMemory : Attr; +def UWTable : Attr; +def ZExt : Attr; Index: lib/Analysis/IPA/InlineCost.cpp =================================================================== --- lib/Analysis/IPA/InlineCost.cpp +++ lib/Analysis/IPA/InlineCost.cpp @@ -1284,22 +1284,6 @@ return getInlineCost(CS, CS.getCalledFunction(), Threshold); } -/// \brief Test that two functions either have or have not the given attribute -/// at the same time. -static bool attributeMatches(Function *F1, Function *F2, - Attribute::AttrKind Attr) { - return F1->hasFnAttribute(Attr) == F2->hasFnAttribute(Attr); -} - -/// \brief Test that there are no attribute conflicts between Caller and Callee -/// that prevent inlining. -static bool functionsHaveCompatibleAttributes(Function *Caller, - Function *Callee) { - return attributeMatches(Caller, Callee, Attribute::SanitizeAddress) && - attributeMatches(Caller, Callee, Attribute::SanitizeMemory) && - attributeMatches(Caller, Callee, Attribute::SanitizeThread); -} - InlineCost InlineCostAnalysis::getInlineCost(CallSite CS, Function *Callee, int Threshold) { // Cannot inline indirect calls. @@ -1316,7 +1300,7 @@ // Never inline functions with conflicting attributes (unless callee has // always-inline attribute). - if (!functionsHaveCompatibleAttributes(CS.getCaller(), Callee)) + if (!hasCompatibleFnAttrs(*CS.getCaller(), *Callee)) return llvm::InlineCost::getNever(); // Don't inline this call if the caller has the optnone attribute. @@ -1347,6 +1331,12 @@ return llvm::InlineCost::get(CA.getCost(), CA.getThreshold()); } +bool InlineCostAnalysis::hasCompatibleFnAttrs(const Function &Caller, + const Function &Callee) const { + return AttributeFuncs::hasCompatibleFnAttrs(Caller, Callee) && + TTIWP->hasCompatibleFnAttrs(Caller, Callee); +} + bool InlineCostAnalysis::isInlineViable(Function &F) { bool ReturnsTwice = F.hasFnAttribute(Attribute::ReturnsTwice); for (Function::iterator BI = F.begin(), BE = F.end(); BI != BE; ++BI) { Index: lib/Analysis/TargetTransformInfo.cpp =================================================================== --- lib/Analysis/TargetTransformInfo.cpp +++ lib/Analysis/TargetTransformInfo.cpp @@ -271,13 +271,19 @@ TargetIRAnalysis::TargetIRAnalysis() : TTICallback(&getDefaultTTI) {} TargetIRAnalysis::TargetIRAnalysis( - std::function TTICallback) - : TTICallback(TTICallback) {} + std::function TTICallback, + FnAttrsCheckerTy FnAttrsChecker) + : TTICallback(TTICallback), FnAttrsChecker(FnAttrsChecker) {} TargetIRAnalysis::Result TargetIRAnalysis::run(Function &F) { return TTICallback(F); } +bool TargetIRAnalysis::hasCompatibleFnAttrs(const Function &Caller, + const Function &Callee) const { + return !FnAttrsChecker || FnAttrsChecker(Caller, Callee); +} + char TargetIRAnalysis::PassID; TargetIRAnalysis::Result TargetIRAnalysis::getDefaultTTI(Function &F) { @@ -309,6 +315,11 @@ return *TTI; } +bool TargetTransformInfoWrapperPass::hasCompatibleFnAttrs( + const Function &Caller, const Function &Callee) const { + return TIRA.hasCompatibleFnAttrs(Caller, Callee); +} + ImmutablePass * llvm::createTargetTransformInfoWrapperPass(TargetIRAnalysis TIRA) { return new TargetTransformInfoWrapperPass(std::move(TIRA)); Index: lib/CodeGen/LLVMTargetMachine.cpp =================================================================== --- lib/CodeGen/LLVMTargetMachine.cpp +++ lib/CodeGen/LLVMTargetMachine.cpp @@ -78,7 +78,7 @@ TargetIRAnalysis LLVMTargetMachine::getTargetIRAnalysis() { return TargetIRAnalysis([this](Function &F) { return TargetTransformInfo(BasicTTIImpl(this, F)); - }); + }, nullptr); } /// addPassesToX helper drives creation and initialization of TargetPassConfig. Index: lib/IR/Attributes.cpp =================================================================== --- lib/IR/Attributes.cpp +++ lib/IR/Attributes.cpp @@ -14,6 +14,7 @@ //===----------------------------------------------------------------------===// #include "llvm/IR/Attributes.h" +#include "llvm/IR/Function.h" #include "AttributeImpl.h" #include "LLVMContextImpl.h" #include "llvm/ADT/STLExtras.h" @@ -1268,3 +1269,12 @@ return AttributeSet::get(Ty->getContext(), Index, Incompatible); } + +#include "FnAttrCompatCheck.inc" + +/// \brief Test that there are no attribute conflicts between Caller and Callee +/// that prevent inlining. +bool AttributeFuncs::hasCompatibleFnAttrs(const Function &Caller, + const Function &Callee) { + return ::hasCompatibleFnAttrs(Caller, Callee); +} Index: lib/IR/Makefile =================================================================== --- lib/IR/Makefile +++ lib/IR/Makefile @@ -10,14 +10,19 @@ LIBRARYNAME = LLVMCore BUILD_ARCHIVE = 1 -BUILT_SOURCES = $(PROJ_OBJ_ROOT)/include/llvm/IR/Intrinsics.gen +BUILT_SOURCES = $(PROJ_OBJ_ROOT)/include/llvm/IR/Intrinsics.gen \ + $(PROJ_OBJ_ROOT)/include/llvm/IR/EnumAttributes.inc \ + $(PROJ_OBJ_ROOT)/lib/IR/FnAttrCompatCheck.inc include $(LEVEL)/Makefile.common GENFILE:=$(PROJ_OBJ_ROOT)/include/llvm/IR/Intrinsics.gen +ENUMATTRINCFILE:=$(PROJ_OBJ_ROOT)/include/llvm/IR/EnumAttributes.inc +FNATTRCHECKINCFILE:=$(PROJ_OBJ_ROOT)/lib/IR/FnAttrCompatCheck.inc INTRINSICTD := $(PROJ_SRC_ROOT)/include/llvm/IR/Intrinsics.td INTRINSICTDS := $(wildcard $(PROJ_SRC_ROOT)/include/llvm/IR/Intrinsics*.td) +ENUMATTRIBUTESTD := $(PROJ_SRC_ROOT)/include/llvm/IR/EnumAttributes.td $(ObjDir)/Intrinsics.gen.tmp: $(ObjDir)/.dir $(INTRINSICTDS) $(LLVM_TBLGEN) $(Echo) Building Intrinsics.gen.tmp from Intrinsics.td @@ -28,6 +33,32 @@ $(EchoCmd) Updated Intrinsics.gen because Intrinsics.gen.tmp \ changed significantly. ) +$(ObjDir)/EnumAttributes.inc.tmp: $(ObjDir)/.dir $(ENUMATTRIBUTESTD) $(LLVM_TBLGEN) + $(Echo) Building EnumAttributes.inc.tmp from $(ENUMATTRIBUTESTD) + $(Verb) $(LLVMTableGen) $(call SYSPATH, $(ENUMATTRIBUTESTD)) -o $(call SYSPATH, $@) -gen-attr-enum + +$(ENUMATTRINCFILE): $(ObjDir)/EnumAttributes.inc.tmp $(PROJ_OBJ_ROOT)/include/llvm/IR/.dir + $(Verb) $(CMP) -s $@ $< || ( $(CP) $< $@ && \ + $(EchoCmd) Updated EnumAttributes.inc because EnumAttributes.inc.tmp \ + changed significantly. ) + +$(ObjDir)/FnAttrCompatCheck.inc.tmp: $(ObjDir)/.dir $(ENUMATTRIBUTESTD) $(LLVM_TBLGEN) + $(Echo) Building FnAttrCompatCheck.inc.tmp from $(ENUMATTRIBUTESTD) + $(Verb) $(LLVMTableGen) $(call SYSPATH, $(ENUMATTRIBUTESTD)) -o $(call SYSPATH, $@) -gen-fnattr-compat-check + +$(FNATTRCHECKINCFILE): $(ObjDir)/FnAttrCompatCheck.inc.tmp $(PROJ_OBJ_ROOT)/include/llvm/IR/.dir + $(Verb) $(CMP) -s $@ $< || ( $(CP) $< $@ && \ + $(EchoCmd) Updated FnAttrCompatCheck.inc because FnAttrCompatCheck.inc.tmp \ + changed significantly. ) + install-local:: $(GENFILE) $(Echo) Installing $(DESTDIR)$(PROJ_includedir)/llvm/IR/Intrinsics.gen $(Verb) $(DataInstall) $(GENFILE) $(DESTDIR)$(PROJ_includedir)/llvm/IR/Intrinsics.gen + +install-local:: $(ENUMATTRINCFILE) + $(Echo) Installing $(DESTDIR)$(PROJ_includedir)/llvm/IR/EnumAttributes.inc + $(Verb) $(DataInstall) $(ENUMATTRINCFILE) $(DESTDIR)$(PROJ_includedir)/llvm/IR/EnumAttributes.inc + +install-local:: $(FNATTRCHECKINCFILE) + $(Echo) Installing $(DESTDIR)$(PROJ_libdir)/IR/FnAttrCompatCheck.inc + $(Verb) $(DataInstall) $(FNATTRCHECKINCFILE) $(DESTDIR)$(PROJ_libdir)/IR/FnAttrCompatCheck.inc Index: lib/Target/AArch64/AArch64TargetMachine.cpp =================================================================== --- lib/Target/AArch64/AArch64TargetMachine.cpp +++ lib/Target/AArch64/AArch64TargetMachine.cpp @@ -196,7 +196,7 @@ TargetIRAnalysis AArch64TargetMachine::getTargetIRAnalysis() { return TargetIRAnalysis([this](Function &F) { return TargetTransformInfo(AArch64TTIImpl(this, F)); - }); + }, nullptr); } TargetPassConfig *AArch64TargetMachine::createPassConfig(PassManagerBase &PM) { Index: lib/Target/ARM/ARMTargetMachine.cpp =================================================================== --- lib/Target/ARM/ARMTargetMachine.cpp +++ lib/Target/ARM/ARMTargetMachine.cpp @@ -213,8 +213,9 @@ } TargetIRAnalysis ARMBaseTargetMachine::getTargetIRAnalysis() { - return TargetIRAnalysis( - [this](Function &F) { return TargetTransformInfo(ARMTTIImpl(this, F)); }); + return TargetIRAnalysis([this](Function &F) { + return TargetTransformInfo(ARMTTIImpl(this, F)); + }, nullptr); } Index: lib/Target/Mips/MipsTargetMachine.cpp =================================================================== --- lib/Target/Mips/MipsTargetMachine.cpp +++ lib/Target/Mips/MipsTargetMachine.cpp @@ -242,7 +242,7 @@ DEBUG(errs() << "Target Transform Info Pass Added\n"); return TargetTransformInfo(BasicTTIImpl(this, F)); - }); + }, nullptr); } // Implemented by targets that want to run passes immediately before Index: lib/Target/NVPTX/NVPTXTargetMachine.cpp =================================================================== --- lib/Target/NVPTX/NVPTXTargetMachine.cpp +++ lib/Target/NVPTX/NVPTXTargetMachine.cpp @@ -141,8 +141,9 @@ } TargetIRAnalysis NVPTXTargetMachine::getTargetIRAnalysis() { - return TargetIRAnalysis( - [this](Function &) { return TargetTransformInfo(NVPTXTTIImpl(this)); }); + return TargetIRAnalysis([this](Function &) { + return TargetTransformInfo(NVPTXTTIImpl(this)); + }, nullptr); } void NVPTXPassConfig::addIRPasses() { Index: lib/Target/PowerPC/PPCTargetMachine.cpp =================================================================== --- lib/Target/PowerPC/PPCTargetMachine.cpp +++ lib/Target/PowerPC/PPCTargetMachine.cpp @@ -320,6 +320,7 @@ } TargetIRAnalysis PPCTargetMachine::getTargetIRAnalysis() { - return TargetIRAnalysis( - [this](Function &F) { return TargetTransformInfo(PPCTTIImpl(this, F)); }); + return TargetIRAnalysis([this](Function &F) { + return TargetTransformInfo(PPCTTIImpl(this, F)); + }, nullptr); } Index: lib/Target/R600/AMDGPUTargetMachine.cpp =================================================================== --- lib/Target/R600/AMDGPUTargetMachine.cpp +++ lib/Target/R600/AMDGPUTargetMachine.cpp @@ -156,8 +156,9 @@ } // End of anonymous namespace TargetIRAnalysis AMDGPUTargetMachine::getTargetIRAnalysis() { - return TargetIRAnalysis( - [this](Function &F) { return TargetTransformInfo(AMDGPUTTIImpl(this)); }); + return TargetIRAnalysis([this](Function &F) { + return TargetTransformInfo(AMDGPUTTIImpl(this)); + }, nullptr); } void AMDGPUPassConfig::addIRPasses() { Index: lib/Target/TargetMachine.cpp =================================================================== --- lib/Target/TargetMachine.cpp +++ lib/Target/TargetMachine.cpp @@ -147,8 +147,9 @@ } TargetIRAnalysis TargetMachine::getTargetIRAnalysis() { - return TargetIRAnalysis( - [this](Function &) { return TargetTransformInfo(getDataLayout()); }); + return TargetIRAnalysis([this](Function &) { + return TargetTransformInfo(getDataLayout()); + }, nullptr); } static bool canUsePrivateLabel(const MCAsmInfo &AsmInfo, Index: lib/Target/X86/X86TargetMachine.cpp =================================================================== --- lib/Target/X86/X86TargetMachine.cpp +++ lib/Target/X86/X86TargetMachine.cpp @@ -162,8 +162,9 @@ //===----------------------------------------------------------------------===// TargetIRAnalysis X86TargetMachine::getTargetIRAnalysis() { - return TargetIRAnalysis( - [this](Function &F) { return TargetTransformInfo(X86TTIImpl(this, F)); }); + return TargetIRAnalysis([this](Function &F) { + return TargetTransformInfo(X86TTIImpl(this, F)); + }, nullptr); } Index: lib/Target/XCore/XCoreTargetMachine.cpp =================================================================== --- lib/Target/XCore/XCoreTargetMachine.cpp +++ lib/Target/XCore/XCoreTargetMachine.cpp @@ -84,6 +84,7 @@ } TargetIRAnalysis XCoreTargetMachine::getTargetIRAnalysis() { - return TargetIRAnalysis( - [this](Function &) { return TargetTransformInfo(XCoreTTIImpl(this)); }); + return TargetIRAnalysis([this](Function &) { + return TargetTransformInfo(XCoreTTIImpl(this)); + }, nullptr); } Index: utils/TableGen/Attribute.cpp =================================================================== --- /dev/null +++ utils/TableGen/Attribute.cpp @@ -0,0 +1,96 @@ +//===- Attribute.cpp - Generate attributes --------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/TableGen/Error.h" +#include "llvm/TableGen/Record.h" +#include +#include +#include +using namespace llvm; + +#define DEBUG_TYPE "attr-enum" + +namespace { + +class Attribute { +private: + RecordKeeper &Records; +public: + Attribute(RecordKeeper &R) : Records(R) {} + + void emitTargetIndependentEnums(raw_ostream &OS); + void emitFnAttrCompatCheck(raw_ostream &OS, bool IsStringAttr); + +private: +}; + +} // End anonymous namespace. + +void Attribute::emitTargetIndependentEnums(raw_ostream &OS) { + const std::vector &Attrs = + Records.getAllDerivedDefinitions("Attr"); + + for (auto A : Attrs) { + OS << A->getName() << ",\n"; + } +} + +void Attribute::emitFnAttrCompatCheck(raw_ostream &OS, bool IsStringAttr) { + const std::vector &Attrs = + Records.getAllDerivedDefinitions("Attr"); + + OS << "template\n"; + OS << "static bool attributeMatches(const Function &F1, const Function &F2,\n" + << " AttrTy Attr) {\n" + << " return F1.getFnAttribute(Attr) == F2.getFnAttribute(Attr);\n" + << "}\n\n"; + + OS << "static bool hasCompatibleFnAttrs(const Function &Caller,\n" + << " const Function &Callee) {\n"; + + std::string NameSpace, Q; + + if (IsStringAttr) { + OS << " typedef const char * EltTy;\n\n"; + Q = "\""; + } else { + OS << " typedef Attribute::AttrKind EltTy;\n\n"; + NameSpace = "Attribute::"; + } + + OS << " EltTy CheckFnAttrCompat[] = {\n"; + for (auto A : Attrs) + if (A->getValueAsBit("CheckCompat")) + OS << " " << NameSpace << Q << A->getName() << Q << ",\n"; + OS << " };\n\n"; + + OS << " for (auto A : CheckFnAttrCompat)\n"; + OS << " if (!attributeMatches(Caller, Callee, A))\n"; + OS << " return false;\n\n"; + OS << " return true;\n"; + OS << "}\n"; +} + +namespace llvm { + +void EmitAttributeEnum(RecordKeeper &RK, raw_ostream &OS) { + Attribute(RK).emitTargetIndependentEnums(OS); +} + +void EmitFnAttrCompatCheck(RecordKeeper &RK, raw_ostream &OS) { + Attribute(RK).emitFnAttrCompatCheck(OS, false); +} + +void EmitTargetFnAttrCompatCheck(RecordKeeper &RK, raw_ostream &OS) { + Attribute(RK).emitFnAttrCompatCheck(OS, true); +} + +} // End llvm namespace. Index: utils/TableGen/TableGen.cpp =================================================================== --- utils/TableGen/TableGen.cpp +++ utils/TableGen/TableGen.cpp @@ -41,7 +41,10 @@ PrintEnums, PrintSets, GenOptParserDefs, - GenCTags + GenCTags, + GenAttributeEnum, + GenFnAttrCompatCheck, + GenTargetFnAttrCompatCheck }; namespace { @@ -85,6 +88,14 @@ "Generate option definitions"), clEnumValN(GenCTags, "gen-ctags", "Generate ctags-compatible index"), + clEnumValN(GenAttributeEnum, "gen-attr-enum", + "Generate attribute enums"), + clEnumValN(GenFnAttrCompatCheck, + "gen-fnattr-compat-check", + "Generate function attribute compatiblity"), + clEnumValN(GenTargetFnAttrCompatCheck, + "gen-target-fnattr-compat-check", + "Generate target function attribute compatiblity"), clEnumValEnd)); cl::opt @@ -165,6 +176,15 @@ case GenCTags: EmitCTags(Records, OS); break; + case GenAttributeEnum: + EmitAttributeEnum(Records, OS); + break; + case GenFnAttrCompatCheck: + EmitFnAttrCompatCheck(Records, OS); + break; + case GenTargetFnAttrCompatCheck: + EmitTargetFnAttrCompatCheck(Records, OS); + break; } return false; Index: utils/TableGen/TableGenBackends.h =================================================================== --- utils/TableGen/TableGenBackends.h +++ utils/TableGen/TableGenBackends.h @@ -78,6 +78,9 @@ void EmitMapTable(RecordKeeper &RK, raw_ostream &OS); void EmitOptParser(RecordKeeper &RK, raw_ostream &OS); void EmitCTags(RecordKeeper &RK, raw_ostream &OS); +void EmitAttributeEnum(RecordKeeper &RK, raw_ostream &OS); +void EmitFnAttrCompatCheck(RecordKeeper &RK, raw_ostream &OS); +void EmitTargetFnAttrCompatCheck(RecordKeeper &RK, raw_ostream &OS); } // End llvm namespace