Adding an annotation that gets to the backend
I wanted to mark certain functions for further processing in the back-end, so I needed to add an annotation that made it through clang. The offical docs on how to add an attribute don't have everything you need to get it passed through to llvm. What I have here starts with what is in the official doc and then adds the extra stuff to get it passed to the backedn.
(All paths to source files are relative to $LLVMBASE
-
add definition of the
__attribute__
to Attr.td:// mark functions which can be called as a PRSC def YourAttribute : InheritableAttr { let Spellings = [GNU<"yourAttribute">]; let Subjects = SubjectList<[Function]>; let Documentation = [YourAttributeDocs]; }
-
add the docs for the new
__attribute__
to AttrDocs.td:def YourAttributeDocs : Documentation { let Category = DocCatFunction; let Heading = "Your Heading"; let Content = [{ Clang supports the GNU style ``__attribute__((yourAttribute))`` attribute on functions which can invoked as blah blah. }]; }
-
add attribute to Attributes.td so it can get passed to llvm
def YourAttribute : EnumAttr<"yourAttribute">;
-
In Attributes.cpp add the code to turn the attribute into a string for the llvm file in
getAsString
.if (hasAttribute(Attribute::YourAttribute)) return "yourAttribute";
-
in Verifier.cpp add
Attribute::YourAttribute
to the list of attributes that are function only attributes in the predicateisFuncOnlyAttr
. -
In SemaDeclAttr.cpp process the
__attribute__
. Added a case to the switch inProcessDeclAttribute
with a call to a simple function which checks that attribute is attached to a function and then just adds it by defaulting tohandleSimpleAttribute
. Not sure I need the check since it seems so basic.// must be on a function, otherwise any is ok static void handleYourAttributeAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (!isFunctionOrMethod(D)) { S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type) << "'yourAttribute'" << ExpectedFunctionOrMethod; return; } handleSimpleAttribute<YourAttributeAttr>(S, D, Attr); }
-
attach attribute to function definition when generating code in CodeGenModule.cpp. Did it in
CodeGenModule::SetLLVMFunctionAttributesForDefinition
// we check for yourAttribute attribute on functions if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) { if (FD->hasAttr<YourAttributeAttr>()) { B.addAttribute(llvm::Attribute::YourAttribute); } }
Next into llvm, so it can be parsed and written out as a .bc
-
in LLToken.h added
kw_yourAttribute
tollvm::lltok::Kind
. -
LLLexer.cpp added
KEYWORD(yourAttribute);
tolltok::Kind LLLexer::LexIdentifier
. -
LLParser.cpp added code to turn keyword into the IR attribute in
LLParser::ParseFnAttributeValuePairs
.case lltok::kw_yourAttribute: B.addAttribute(Attribute::YourAttribute); break;
-
LLVMBitCodes.h added a new entry to end of
AttributeKindCodes
.ATTR_KIND_YourAttribute = 55,
-
And, then in BitcodeWriter.cpp add a case to the big switch in
getAttrKindEncoding
.case Attribute::YourAttribute: return bitc::ATTR_KIND_YourAttribute;
-
Likewise, in BitCodeReader.cpp, add the reverse case to the big switch in
getAttrFromCode
:case bitc::ATTR_KIND_YourAttribute: return Attribute::YourAttribute;