wsmoses created this revision.
wsmoses added a reviewer: jdoerfert.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

This (work in progress) diff adds three new attributes to clang 
(__attribute__((LLVMFN(string))), __attribute__((LLVMARG(paramidx, string))), 
__attribute__((LLVMRET(paramidx, string))) ) for passing attributes down to 
LLVM.

This is useful for allowing users, tools, or test cases to specify LLVM 
attributes that may not have a representation in clang.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D63845

Files:
  clang/include/clang/Basic/Attr.td
  clang/lib/CodeGen/CodeGenFunction.cpp
  clang/lib/Sema/SemaDeclAttr.cpp
  clang/utils/TableGen/ClangAttrEmitter.cpp

Index: clang/utils/TableGen/ClangAttrEmitter.cpp
===================================================================
--- clang/utils/TableGen/ClangAttrEmitter.cpp
+++ clang/utils/TableGen/ClangAttrEmitter.cpp
@@ -1290,6 +1290,8 @@
     Ptr = llvm::make_unique<VariadicParamIdxArgument>(Arg, Attr);
   else if (ArgName == "VariadicParamOrParamIdxArgument")
     Ptr = llvm::make_unique<VariadicParamOrParamIdxArgument>(Arg, Attr);
+  else if (ArgName == "ParamOrParamIdxArgument")
+    Ptr = llvm::make_unique<SimpleArgument>(Arg, Attr, "int");
   else if (ArgName == "ParamIdxArgument")
     Ptr = llvm::make_unique<SimpleArgument>(Arg, Attr, "ParamIdx");
   else if (ArgName == "VariadicIdentifierArgument")
@@ -2184,6 +2186,7 @@
          llvm::StringSwitch<bool>(
              Arg->getSuperClasses().back().first->getName())
              .Case("VariadicParamOrParamIdxArgument", true)
+             .Case("ParamOrParamIdxArgument", true)
              .Default(false);
 }
 
Index: clang/lib/Sema/SemaDeclAttr.cpp
===================================================================
--- clang/lib/Sema/SemaDeclAttr.cpp
+++ clang/lib/Sema/SemaDeclAttr.cpp
@@ -3456,20 +3456,9 @@
     D->addAttr(NewAttr);
 }
 
-/// Handle __attribute__((callback(CalleeIdx, PayloadIdx0, ...))) attributes.
-static void handleCallbackAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
-  // The index that identifies the callback callee is mandatory.
-  if (AL.getNumArgs() == 0) {
-    S.Diag(AL.getLoc(), diag::err_callback_attribute_no_callee)
-        << AL.getRange();
-    return;
-  }
-
-  bool HasImplicitThisParam = isInstanceMethod(D);
-  int32_t NumArgs = getFunctionOrMethodNumParams(D);
-
-  FunctionDecl *FD = D->getAsFunction();
-  assert(FD && "Expected a function declaration!");
+static int32_t getParamFromNameOrIndex(Sema &S, FunctionDecl *FD, const ParsedAttr &AL, unsigned I) {
+  bool HasImplicitThisParam = isInstanceMethod(FD);
+  int32_t NumArgs = getFunctionOrMethodNumParams(FD);
 
   llvm::StringMap<int> NameIdxMapping;
   NameIdxMapping["__"] = -1;
@@ -3482,8 +3471,6 @@
 
   auto UnknownName = NameIdxMapping.end();
 
-  SmallVector<int, 8> EncodingIndices;
-  for (unsigned I = 0, E = AL.getNumArgs(); I < E; ++I) {
     SourceRange SR;
     int32_t ArgIdx;
 
@@ -3493,7 +3480,7 @@
       if (It == UnknownName) {
         S.Diag(AL.getLoc(), diag::err_callback_attribute_argument_unknown)
             << IdLoc->Ident << IdLoc->Loc;
-        return;
+        return -1;
       }
 
       SR = SourceRange(IdLoc->Loc);
@@ -3506,14 +3493,14 @@
                                false)) {
         S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds)
             << AL << (I + 1) << IdxExpr->getSourceRange();
-        return;
+        return -1;
       }
 
       // Check oob, excluding the special values, 0 and -1.
       if (ArgIdx < -1 || ArgIdx > NumArgs) {
         S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds)
             << AL << (I + 1) << IdxExpr->getSourceRange();
-        return;
+        return -1;
       }
 
       SR = IdxExpr->getSourceRange();
@@ -3524,7 +3511,7 @@
     if (ArgIdx == 0 && !HasImplicitThisParam) {
       S.Diag(AL.getLoc(), diag::err_callback_implicit_this_not_available)
           << (I + 1) << SR;
-      return;
+      return -1;
     }
 
     // Adjust for the case we do not have an implicit "this" parameter. In this
@@ -3532,9 +3519,31 @@
     if (!HasImplicitThisParam && ArgIdx > 0)
       ArgIdx -= 1;
 
+    return ArgIdx;
+}
+
+/// Handle __attribute__((callback(CalleeIdx, PayloadIdx0, ...))) attributes.
+static void handleCallbackAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+  // The index that identifies the callback callee is mandatory.
+  if (AL.getNumArgs() == 0) {
+    S.Diag(AL.getLoc(), diag::err_callback_attribute_no_callee)
+        << AL.getRange();
+    return;
+  }
+
+
+  FunctionDecl *FD = D->getAsFunction();
+  assert(FD && "Expected a function declaration!");
+
+
+  SmallVector<int, 8> EncodingIndices;
+  for (unsigned I = 0, E = AL.getNumArgs(); I < E; ++I) {
+    int32_t ArgIdx = getParamFromNameOrIndex(S, FD, AL, I);
+    if (ArgIdx == -1) return;
     EncodingIndices.push_back(ArgIdx);
   }
 
+  bool HasImplicitThisParam = isInstanceMethod(FD);
   int CalleeIdx = EncodingIndices.front();
   // Check if the callee index is proper, thus not "this" and not "unknown".
   // This means the "CalleeIdx" has to be non-negative if "HasImplicitThisParam"
@@ -3746,12 +3755,15 @@
   }
 
   Expr *E = AL.getArgAsExpr(0);
-  ParamIdx Idx;
-  checkFunctionOrMethodParameterIndex(S, D, AL, 0, E, Idx);
+
+  FunctionDecl *FD = D->getAsFunction();
+  assert(FD && "Expected a function declaration!");
+
+  int32_t ArgIdx = getParamFromNameOrIndex(S, FD, AL, 0);
   StringRef Str;
   S.checkStringLiteralArgumentAttr(AL, 1, Str);
   
-  D->addAttr(::new (S.Context) AttrType(AL.getRange(), S.Context, Idx, Str,
+  D->addAttr(::new (S.Context) AttrType(AL.getRange(), S.Context, ArgIdx, Str,
                                          AL.getAttributeSpellingListIndex()));
 }
 
Index: clang/lib/CodeGen/CodeGenFunction.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenFunction.cpp
+++ clang/lib/CodeGen/CodeGenFunction.cpp
@@ -737,7 +737,7 @@
         }
         if (auto atr = dyn_cast<LLVMARGAttr>(a)) {
             std::pair<StringRef, StringRef> attributeandvalue = atr->getAttrName().split('=');
-            unsigned index = llvm::AttributeList::FirstArgIndex + atr->getParamIndex().getLLVMIndex();
+            unsigned index = llvm::AttributeList::FirstArgIndex + atr->getParamIndex(); //.getLLVMIndex();
             llvm::Attribute::AttrKind attrkind = llvm::Attribute::parseAttrKind(attributeandvalue.first);
             if (attrkind != llvm::Attribute::None) {
                 assert(attributeandvalue.second.size() == 0);
Index: clang/include/clang/Basic/Attr.td
===================================================================
--- clang/include/clang/Basic/Attr.td
+++ clang/include/clang/Basic/Attr.td
@@ -187,6 +187,9 @@
 // A list of identifiers matching parameters or ParamIdx indices.
 class VariadicParamOrParamIdxArgument<string name> : Argument<name, 1>;
 
+// Like VariadicParamOrParamIdxArgument but for a single function parameter index.
+class ParamOrParamIdxArgument<string name, bit opt = 0> : Argument<name, opt>;
+
 // Like VariadicParamIdxArgument but for a single function parameter index.
 class ParamIdxArgument<string name, bit opt = 0> : Argument<name, opt>;
 
@@ -1639,7 +1642,7 @@
 
 def LLVMARG : InheritableAttr {
   let Spellings = [GCC<"LLVMARG">];
-  let Args = [ParamIdxArgument<"ParamIndex">, StringArgument<"AttrName">];
+  let Args = [ParamOrParamIdxArgument<"ParamIndex">, StringArgument<"AttrName">];
   let Documentation = [Undocumented];
 }
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to