Allocator Attribute
diff --git a/enzyme/Enzyme/Clang/EnzymeClang.cpp b/enzyme/Enzyme/Clang/EnzymeClang.cpp index e731fbd..0d41413 100644 --- a/enzyme/Enzyme/Clang/EnzymeClang.cpp +++ b/enzyme/Enzyme/Clang/EnzymeClang.cpp
@@ -80,3 +80,79 @@ // register the PluginASTAction in the registry. static clang::FrontendPluginRegistry::Add<EnzymeAction<EnzymePlugin>> X("enzyme", "Enzyme Plugin"); + + +#include "clang/AST/ASTContext.h" +#include "clang/AST/Attr.h" +#include "clang/Sema/ParsedAttr.h" +#include "clang/Sema/Sema.h" +#include "clang/Sema/SemaDiagnostic.h" +#include "llvm/IR/Attributes.h" +using namespace clang; + +namespace { + +struct EnzymeAttrInfo : public ParsedAttrInfo { + EnzymeAttrInfo() { + OptArgs = 2; + // GNU-style __attribute__(("example")) and C++-style [[example]] + static constexpr Spelling S[] = {{ParsedAttr::AS_GNU, "enzyme_allocator"}, + {ParsedAttr::AS_CXX11, "enzyme_allocator"}}; + Spellings = S; + } + + bool diagAppertainsToDecl(Sema &S, const ParsedAttr &Attr, + const Decl *D) const override { + // This attribute appertains to functions only. + if (!isa<FunctionDecl>(D)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str) + << Attr << "functions"; + return false; + } + return true; + } + + AttrHandling handleDeclAttribute(Sema &S, Decl *D, + const ParsedAttr &Attr) const override { + // Check if the decl is at file scope. + if (!D->getDeclContext()->isFileContext()) { + unsigned ID = S.getDiagnostics().getCustomDiagID( + DiagnosticsEngine::Error, + "'enzyme_allocator' attribute only allowed at file scope"); + S.Diag(Attr.getLoc(), ID); + return AttributeNotApplied; + } + + if (Attr.getNumArgs() == 0) { + unsigned ID = S.getDiagnostics().getCustomDiagID( + DiagnosticsEngine::Error, + "'enzyme_allocator' attribute requires argument of allocation size"); + S.Diag(Attr.getLoc(), ID); + return AttributeNotApplied; + } + + auto *Arg0 = Attr.getArgAsExpr(0); + IntegerLiteral *Literal = + dyn_cast<IntegerLiteral>(Arg0->IgnoreParenCasts()); + if (!Literal) { + unsigned ID = S.getDiagnostics().getCustomDiagID( + DiagnosticsEngine::Error, "first argument to the 'enzyme_allocator' " + "attribute must be a integer literal"); + S.Diag(Attr.getLoc(), ID); + return AttributeNotApplied; + } + SmallVector<Expr *, 16> ArgsBuf; + for (unsigned i = 0; i < Attr.getNumArgs(); i++) { + ArgsBuf.push_back(Attr.getArgAsExpr(i)); + } + D->addAttr(AnnotateAttr::Create(S.Context, "enzyme", ArgsBuf.data(), + ArgsBuf.size(), Attr.getRange())); + D->addAttr(Attribute::NoInline); + return AttributeApplied; + } +}; + +} // namespace + +static ParsedAttrInfoRegistry::Add<EnzymeAttrInfo> X("enzyme", "Enzyme Plugin"); +