wsmoses updated this revision to Diff 211371.
wsmoses edited the summary of this revision.

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D65169/new/

https://reviews.llvm.org/D65169

Files:
  clang/include/clang/Basic/Attr.td
  clang/include/clang/Basic/DiagnosticFrontendKinds.td
  clang/include/clang/Basic/DiagnosticGroups.td
  clang/lib/CodeGen/CodeGenAction.cpp
  clang/lib/CodeGen/CodeGenFunction.cpp
  clang/lib/Sema/SemaDeclAttr.cpp
  clang/utils/TableGen/ClangAttrEmitter.cpp
  llvm/include/llvm/IR/Attributes.h
  llvm/include/llvm/IR/DiagnosticInfo.h
  llvm/include/llvm/InitializePasses.h
  llvm/include/llvm/LinkAllPasses.h
  llvm/include/llvm/Transforms/Utils.h
  llvm/include/llvm/Transforms/Utils/EmitAnnotations.h
  llvm/lib/IR/Attributes.cpp
  llvm/lib/IR/DiagnosticInfo.cpp
  llvm/lib/Passes/PassBuilder.cpp
  llvm/lib/Transforms/IPO/ForceFunctionAttrs.cpp
  llvm/lib/Transforms/IPO/PassManagerBuilder.cpp
  llvm/lib/Transforms/Utils/CMakeLists.txt
  llvm/lib/Transforms/Utils/EmitAnnotations.cpp
  llvm/lib/Transforms/Utils/Utils.cpp

Index: llvm/lib/Transforms/Utils/Utils.cpp
===================================================================
--- llvm/lib/Transforms/Utils/Utils.cpp
+++ llvm/lib/Transforms/Utils/Utils.cpp
@@ -26,6 +26,7 @@
   initializeAddDiscriminatorsLegacyPassPass(Registry);
   initializeBreakCriticalEdgesPass(Registry);
   initializeCanonicalizeAliasesLegacyPassPass(Registry);
+  initializeEmitAnnotationsLegacyPassPass(Registry);
   initializeInstNamerPass(Registry);
   initializeLCSSAWrapperPassPass(Registry);
   initializeLibCallsShrinkWrapLegacyPassPass(Registry);
Index: llvm/lib/Transforms/Utils/EmitAnnotations.cpp
===================================================================
--- /dev/null
+++ llvm/lib/Transforms/Utils/EmitAnnotations.cpp
@@ -0,0 +1,96 @@
+//===-- UnrollLoop.cpp - Loop unrolling utilities -------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements some loop unrolling utilities. It does not define any
+// actual pass or policy, but provides a single function to perform loop
+// unrolling.
+//
+// The process of unrolling can produce extraneous basic blocks linked with
+// unconditional branches.  This will be corrected in the future.
+//
+//===----------------------------------------------------------------------===//
+
+#include <string>
+#include "llvm/Analysis/OptimizationRemarkEmitter.h"
+#include "llvm/Pass.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Transforms/Utils.h"
+#include "llvm/Transforms/Utils/EmitAnnotations.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "emit-annotations"
+
+std::string fixQuotes(std::string str) {
+    str.erase(std::remove(str.begin(), str.end(), '"'), str.end());
+    return '"' + str + '"';
+}
+
+void EmitAnnotations(Function *F, OptimizationRemarkEmitter &ORE) {
+        OptimizationRemarkAnnotation annotations(DEBUG_TYPE, "annotation ", F);
+        AttributeList list = F->getAttributes();
+        for(auto a : list.getFnAttributes()) {
+            annotations << "fn_attr(" << fixQuotes(a.getAsString(true)) << ") ";
+        }
+        for(auto a : list.getRetAttributes()) {
+            annotations << "ret_attr(" << fixQuotes(a.getAsString(true)) << ") ";
+        }
+        for(unsigned i=0; i<F->getFunctionType()->getNumParams(); i++)
+            for(auto a : list.getParamAttributes(i)) {
+            annotations << "arg_attr(" << std::to_string(i) << ", " << fixQuotes(a.getAsString(true)) << ") ";
+        }
+        annotations << "\n";
+      ORE.emit(annotations);
+}
+
+namespace llvm {
+
+struct EmitAnnotationsLegacyPass : public FunctionPass {
+  // Pass identification, replacement for typeid
+  static char ID;
+
+  EmitAnnotationsLegacyPass() : FunctionPass(ID) {
+    initializeEmitAnnotationsLegacyPassPass(*PassRegistry::getPassRegistry());
+  }
+
+  // runOnFunction - To run this pass, first we calculate the alloca
+  // instructions that are safe for promotion, then we promote each one.
+  bool runOnFunction(Function &F) override {
+    OptimizationRemarkEmitter &ORE = getAnalysis<OptimizationRemarkEmitterWrapperPass>().getORE();
+    EmitAnnotations(&F, ORE);
+    return false;
+  }
+
+  void getAnalysisUsage(AnalysisUsage &AU) const override {
+    AU.addRequired<OptimizationRemarkEmitterWrapperPass>();
+    AU.setPreservesCFG();
+  }
+};
+
+} // end anonymous namespace
+
+char EmitAnnotationsLegacyPass::ID = 0;
+
+PreservedAnalyses EmitAnnotationsPass::run(Function &F,
+                                               FunctionAnalysisManager &FM) {
+  OptimizationRemarkEmitter &ORE = FM.getResult<OptimizationRemarkEmitterAnalysis>(F);
+  EmitAnnotations(&F, ORE);
+  return PreservedAnalyses::all();
+}
+
+INITIALIZE_PASS_BEGIN(EmitAnnotationsLegacyPass, "emit-annotation", "Emit annotations", 
+                      false, false)
+INITIALIZE_PASS_DEPENDENCY(OptimizationRemarkEmitterWrapperPass)
+INITIALIZE_PASS_END(EmitAnnotationsLegacyPass, "emit-annotation", "Emit annotations", 
+                    false, false)
+
+FunctionPass *llvm::createEmitAnnotationsPass() {
+  return new EmitAnnotationsLegacyPass();
+}
Index: llvm/lib/Transforms/Utils/CMakeLists.txt
===================================================================
--- llvm/lib/Transforms/Utils/CMakeLists.txt
+++ llvm/lib/Transforms/Utils/CMakeLists.txt
@@ -12,6 +12,7 @@
   CodeExtractor.cpp
   CtorUtils.cpp
   DemoteRegToStack.cpp
+  EmitAnnotations.cpp
   EntryExitInstrumenter.cpp
   EscapeEnumerator.cpp
   Evaluator.cpp
Index: llvm/lib/Transforms/IPO/PassManagerBuilder.cpp
===================================================================
--- llvm/lib/Transforms/IPO/PassManagerBuilder.cpp
+++ llvm/lib/Transforms/IPO/PassManagerBuilder.cpp
@@ -777,7 +777,7 @@
   MPM.add(createCFGSimplificationPass());
 
   addExtensionsToPM(EP_OptimizerLast, MPM);
-
+  MPM.add(createEmitAnnotationsPass());
   if (PrepareForLTO) {
     MPM.add(createCanonicalizeAliasesPass());
     // Rename anon globals to be able to handle them in the summary
Index: llvm/lib/Transforms/IPO/ForceFunctionAttrs.cpp
===================================================================
--- llvm/lib/Transforms/IPO/ForceFunctionAttrs.cpp
+++ llvm/lib/Transforms/IPO/ForceFunctionAttrs.cpp
@@ -24,48 +24,6 @@
                              "example -force-attribute=foo:noinline. This "
                              "option can be specified multiple times."));
 
-static Attribute::AttrKind parseAttrKind(StringRef Kind) {
-  return StringSwitch<Attribute::AttrKind>(Kind)
-      .Case("alwaysinline", Attribute::AlwaysInline)
-      .Case("builtin", Attribute::Builtin)
-      .Case("cold", Attribute::Cold)
-      .Case("convergent", Attribute::Convergent)
-      .Case("inlinehint", Attribute::InlineHint)
-      .Case("jumptable", Attribute::JumpTable)
-      .Case("minsize", Attribute::MinSize)
-      .Case("naked", Attribute::Naked)
-      .Case("nobuiltin", Attribute::NoBuiltin)
-      .Case("noduplicate", Attribute::NoDuplicate)
-      .Case("noimplicitfloat", Attribute::NoImplicitFloat)
-      .Case("noinline", Attribute::NoInline)
-      .Case("nonlazybind", Attribute::NonLazyBind)
-      .Case("noredzone", Attribute::NoRedZone)
-      .Case("noreturn", Attribute::NoReturn)
-      .Case("nocf_check", Attribute::NoCfCheck)
-      .Case("norecurse", Attribute::NoRecurse)
-      .Case("nounwind", Attribute::NoUnwind)
-      .Case("optforfuzzing", Attribute::OptForFuzzing)
-      .Case("optnone", Attribute::OptimizeNone)
-      .Case("optsize", Attribute::OptimizeForSize)
-      .Case("readnone", Attribute::ReadNone)
-      .Case("readonly", Attribute::ReadOnly)
-      .Case("argmemonly", Attribute::ArgMemOnly)
-      .Case("returns_twice", Attribute::ReturnsTwice)
-      .Case("safestack", Attribute::SafeStack)
-      .Case("shadowcallstack", Attribute::ShadowCallStack)
-      .Case("sanitize_address", Attribute::SanitizeAddress)
-      .Case("sanitize_hwaddress", Attribute::SanitizeHWAddress)
-      .Case("sanitize_memory", Attribute::SanitizeMemory)
-      .Case("sanitize_thread", Attribute::SanitizeThread)
-      .Case("speculative_load_hardening", Attribute::SpeculativeLoadHardening)
-      .Case("ssp", Attribute::StackProtect)
-      .Case("sspreq", Attribute::StackProtectReq)
-      .Case("sspstrong", Attribute::StackProtectStrong)
-      .Case("strictfp", Attribute::StrictFP)
-      .Case("uwtable", Attribute::UWTable)
-      .Default(Attribute::None);
-}
-
 /// If F has any forced attributes given on the command line, add them.
 static void addForcedAttributes(Function &F) {
   for (auto &S : ForceAttributes) {
@@ -73,7 +31,7 @@
     if (KV.first != F.getName())
       continue;
 
-    auto Kind = parseAttrKind(KV.second);
+    auto Kind = Attribute::parseAttrKind(KV.second);
     if (Kind == Attribute::None) {
       LLVM_DEBUG(dbgs() << "ForcedAttribute: " << KV.second
                         << " unknown or not handled!\n");
Index: llvm/lib/Passes/PassBuilder.cpp
===================================================================
--- llvm/lib/Passes/PassBuilder.cpp
+++ llvm/lib/Passes/PassBuilder.cpp
@@ -163,6 +163,8 @@
 #include "llvm/Transforms/Utils/BreakCriticalEdges.h"
 #include "llvm/Transforms/Utils/CanonicalizeAliases.h"
 #include "llvm/Transforms/Utils/EntryExitInstrumenter.h"
+#include "llvm/Transforms/Utils.h"
+#include "llvm/Transforms/Utils/EmitAnnotations.h"
 #include "llvm/Transforms/Utils/LCSSA.h"
 #include "llvm/Transforms/Utils/LibCallsShrinkWrap.h"
 #include "llvm/Transforms/Utils/LoopSimplify.h"
@@ -997,6 +999,10 @@
   // Now add the optimization pipeline.
   MPM.addPass(buildModuleOptimizationPipeline(Level, DebugLogging, LTOPreLink));
 
+  FunctionPassManager FPM(DebugLogging);
+  FPM.addPass(EmitAnnotationsPass());
+  MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
+
   return MPM;
 }
 
Index: llvm/lib/IR/DiagnosticInfo.cpp
===================================================================
--- llvm/lib/IR/DiagnosticInfo.cpp
+++ llvm/lib/IR/DiagnosticInfo.cpp
@@ -257,6 +257,13 @@
                                    RemarkName, *Func, Func->getSubprogram(),
                                    &getFirstFunctionBlock(Func)) {}
 
+OptimizationRemark::OptimizationRemark(enum DiagnosticKind kind, const char *PassName,
+                                       StringRef RemarkName,
+                                       const Function *Func)
+    : DiagnosticInfoIROptimization(kind, DS_Remark, PassName,
+                                   RemarkName, *Func, Func->getSubprogram(),
+                                   &getFirstFunctionBlock(Func)) {}
+
 bool OptimizationRemark::isEnabled() const {
   const Function &Fn = getFunction();
   LLVMContext &Ctx = Fn.getContext();
Index: llvm/lib/IR/Attributes.cpp
===================================================================
--- llvm/lib/IR/Attributes.cpp
+++ llvm/lib/IR/Attributes.cpp
@@ -479,6 +479,48 @@
   llvm_unreachable("Unknown attribute");
 }
 
+Attribute::AttrKind Attribute::parseAttrKind(StringRef Kind) {
+  return StringSwitch<Attribute::AttrKind>(Kind)
+      .Case("alwaysinline", Attribute::AlwaysInline)
+      .Case("builtin", Attribute::Builtin)
+      .Case("cold", Attribute::Cold)
+      .Case("convergent", Attribute::Convergent)
+      .Case("inlinehint", Attribute::InlineHint)
+      .Case("jumptable", Attribute::JumpTable)
+      .Case("minsize", Attribute::MinSize)
+      .Case("naked", Attribute::Naked)
+      .Case("nobuiltin", Attribute::NoBuiltin)
+      .Case("noduplicate", Attribute::NoDuplicate)
+      .Case("noimplicitfloat", Attribute::NoImplicitFloat)
+      .Case("noinline", Attribute::NoInline)
+      .Case("nonlazybind", Attribute::NonLazyBind)
+      .Case("noredzone", Attribute::NoRedZone)
+      .Case("noreturn", Attribute::NoReturn)
+      .Case("nocf_check", Attribute::NoCfCheck)
+      .Case("norecurse", Attribute::NoRecurse)
+      .Case("nounwind", Attribute::NoUnwind)
+      .Case("optforfuzzing", Attribute::OptForFuzzing)
+      .Case("optnone", Attribute::OptimizeNone)
+      .Case("optsize", Attribute::OptimizeForSize)
+      .Case("readnone", Attribute::ReadNone)
+      .Case("readonly", Attribute::ReadOnly)
+      .Case("argmemonly", Attribute::ArgMemOnly)
+      .Case("returns_twice", Attribute::ReturnsTwice)
+      .Case("safestack", Attribute::SafeStack)
+      .Case("shadowcallstack", Attribute::ShadowCallStack)
+      .Case("sanitize_address", Attribute::SanitizeAddress)
+      .Case("sanitize_hwaddress", Attribute::SanitizeHWAddress)
+      .Case("sanitize_memory", Attribute::SanitizeMemory)
+      .Case("sanitize_thread", Attribute::SanitizeThread)
+      .Case("speculative_load_hardening", Attribute::SpeculativeLoadHardening)
+      .Case("ssp", Attribute::StackProtect)
+      .Case("sspreq", Attribute::StackProtectReq)
+      .Case("sspstrong", Attribute::StackProtectStrong)
+      .Case("strictfp", Attribute::StrictFP)
+      .Case("uwtable", Attribute::UWTable)
+      .Default(Attribute::None);
+}
+
 bool Attribute::operator<(Attribute A) const {
   if (!pImpl && !A.pImpl) return false;
   if (!pImpl) return true;
Index: llvm/include/llvm/Transforms/Utils/EmitAnnotations.h
===================================================================
--- /dev/null
+++ llvm/include/llvm/Transforms/Utils/EmitAnnotations.h
@@ -0,0 +1,31 @@
+//===-- EmitAnnotations.h - Emit Annotations Pass -----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file emits function annotations
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_UTILS_EMIT_ANNOTATIONS_H
+#define LLVM_TRANSFORMS_UTILS_EMIT_ANNOTATIONS_H
+
+#include "llvm/IR/Module.h"
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+
+/// Simple pass that canonicalizes aliases.
+class EmitAnnotationsPass : public PassInfoMixin<EmitAnnotationsPass> {
+public:
+  EmitAnnotationsPass() = default;
+
+  PreservedAnalyses run(Function &F, FunctionAnalysisManager &FM);
+};
+
+} // end namespace llvm
+
+#endif // LLVM_TRANSFORMS_UTILS_EMIT_ANNOTATIONS_H
Index: llvm/include/llvm/Transforms/Utils.h
===================================================================
--- llvm/include/llvm/Transforms/Utils.h
+++ llvm/include/llvm/Transforms/Utils.h
@@ -98,6 +98,13 @@
 //
 FunctionPass *createPromoteMemoryToRegisterPass();
 
+
+//===----------------------------------------------------------------------===//
+//
+// EmitAnnotations - This pass is used to create annotations about derived LLVM
+// information that can be fed back in through the front end
+FunctionPass *createEmitAnnotationsPass();
+
 //===----------------------------------------------------------------------===//
 //
 // LoopSimplify - Insert Pre-header blocks into the CFG for every function in
Index: llvm/include/llvm/LinkAllPasses.h
===================================================================
--- llvm/include/llvm/LinkAllPasses.h
+++ llvm/include/llvm/LinkAllPasses.h
@@ -100,6 +100,7 @@
       (void) llvm::createDomPrinterPass();
       (void) llvm::createDomOnlyViewerPass();
       (void) llvm::createDomViewerPass();
+      (void) llvm::createEmitAnnotationsPass();
       (void) llvm::createGCOVProfilerPass();
       (void) llvm::createPGOInstrumentationGenLegacyPass();
       (void) llvm::createPGOInstrumentationUseLegacyPass();
Index: llvm/include/llvm/InitializePasses.h
===================================================================
--- llvm/include/llvm/InitializePasses.h
+++ llvm/include/llvm/InitializePasses.h
@@ -136,6 +136,7 @@
 void initializeEarlyTailDuplicatePass(PassRegistry&);
 void initializeEdgeBundlesPass(PassRegistry&);
 void initializeEliminateAvailableExternallyLegacyPassPass(PassRegistry&);
+void initializeEmitAnnotationsLegacyPassPass(PassRegistry&);
 void initializeEntryExitInstrumenterPass(PassRegistry&);
 void initializeExpandMemCmpPassPass(PassRegistry&);
 void initializeExpandPostRAPass(PassRegistry&);
Index: llvm/include/llvm/IR/DiagnosticInfo.h
===================================================================
--- llvm/include/llvm/IR/DiagnosticInfo.h
+++ llvm/include/llvm/IR/DiagnosticInfo.h
@@ -64,6 +64,7 @@
   DK_OptimizationRemarkAnalysis,
   DK_OptimizationRemarkAnalysisFPCommute,
   DK_OptimizationRemarkAnalysisAliasing,
+  DK_OptimizationRemarkAnnotation,
   DK_OptimizationFailure,
   DK_FirstRemark = DK_OptimizationRemark,
   DK_LastRemark = DK_OptimizationFailure,
@@ -688,6 +689,11 @@
   OptimizationRemark(const char *PassName, StringRef RemarkName,
                      const Function *Func);
 
+  /// Same as above, but the debug location and code region are derived from \p
+  /// Func with custom enum.
+  OptimizationRemark(enum DiagnosticKind Kind, const char *PassName, StringRef RemarkName,
+                     const Function *Func);
+
   static bool classof(const DiagnosticInfo *DI) {
     return DI->getKind() == DK_OptimizationRemark;
   }
@@ -819,6 +825,26 @@
                                      PassName, Fn, Loc, Msg) {}
 };
 
+/// Diagnostic information for optimization analysis remarks related to
+/// annotation emission
+class OptimizationRemarkAnnotation : public OptimizationRemark {
+public:
+  /// \p PassName is the name of the pass emitting this diagnostic. If this name
+  /// matches the regular expression given in -Rpass-analysis=, then the
+  /// diagnostic will be emitted. \p RemarkName is a textual identifier for the
+  /// remark (single-word, camel-case). \p Loc is the debug location and \p
+  /// CodeRegion is the region that the optimization operates on (currently only
+  /// block is supported). The front-end will append its own message related to
+  /// options that address floating-point non-commutativity.
+  OptimizationRemarkAnnotation(const char *PassName,
+                                      StringRef RemarkName,
+                                      const Function *Fn)
+      : OptimizationRemark(DK_OptimizationRemarkAnnotation, PassName, RemarkName, Fn) {}
+
+  static bool classof(const DiagnosticInfo *DI) {
+    return DI->getKind() == DK_OptimizationRemarkAnnotation;
+  }
+};
 /// Diagnostic information for optimization analysis remarks related to
 /// floating-point non-commutativity.
 class OptimizationRemarkAnalysisFPCommute : public OptimizationRemarkAnalysis {
Index: llvm/include/llvm/IR/Attributes.h
===================================================================
--- llvm/include/llvm/IR/Attributes.h
+++ llvm/include/llvm/IR/Attributes.h
@@ -192,6 +192,8 @@
   static Attribute fromRawPointer(void *RawPtr) {
     return Attribute(reinterpret_cast<AttributeImpl*>(RawPtr));
   }
+
+  static Attribute::AttrKind parseAttrKind(StringRef Kind);
 };
 
 // Specialized opaque value conversions.
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"
@@ -3737,6 +3746,42 @@
   D->addAttr(::new (Context) AlignValueAttr(TmpAttr));
 }
 
+template <typename AttrType>
+static void handleSimpleIntStringAttribute(Sema &S, Decl *D, const ParsedAttr &AL) {
+  // check the attribute arguments.
+  if (AL.getNumArgs() != 2) {
+    S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
+    return;
+  }
+
+  Expr *E = AL.getArgAsExpr(0);
+
+  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, ArgIdx, Str,
+                                         AL.getAttributeSpellingListIndex()));
+}
+
+template <typename AttrType>
+static void handleSimpleStringAttribute(Sema &S, Decl *D, const ParsedAttr &AL) {
+  // check the attribute arguments.
+  if (AL.getNumArgs() != 1) {
+    S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
+    return;
+  }
+
+  StringRef Str;
+  S.checkStringLiteralArgumentAttr(AL, 0, Str);
+  
+  D->addAttr(::new (S.Context) AttrType(AL.getRange(), S.Context, Str,
+                                         AL.getAttributeSpellingListIndex()));
+}
+
 static void handleAlignedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
   // check the attribute arguments.
   if (AL.getNumArgs() > 1) {
@@ -6618,6 +6663,15 @@
     S.Diag(AL.getLoc(), diag::err_stmt_attribute_invalid_on_decl)
         << AL << D->getLocation();
     break;
+  case ParsedAttr::AT_LLVMFN:
+    handleSimpleStringAttribute<LLVMFNAttr>(S, D, AL);
+    break;
+  case ParsedAttr::AT_LLVMARG:
+    handleSimpleIntStringAttribute<LLVMARGAttr>(S, D, AL);
+    break;
+  case ParsedAttr::AT_LLVMRET:
+    handleSimpleStringAttribute<LLVMRETAttr>(S, D, AL);
+    break;
   case ParsedAttr::AT_Interrupt:
     handleInterruptAttr(S, D, AL);
     break;
Index: clang/lib/CodeGen/CodeGenFunction.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenFunction.cpp
+++ clang/lib/CodeGen/CodeGenFunction.cpp
@@ -730,6 +730,36 @@
       SanOpts.Mask &= ~SanitizerKind::CFIUnrelatedCast;
   }
 
+  if (D) {
+    for(auto a: D->attrs()) {
+        if (auto atr = dyn_cast<LLVMFNAttr>(a)) {
+            Fn->addFnAttr(atr->getAttrName());
+        }
+        if (auto atr = dyn_cast<LLVMARGAttr>(a)) {
+            std::pair<StringRef, StringRef> attributeandvalue = atr->getAttrName().split('=');
+            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);
+                Fn->addParamAttr(index, llvm::Attribute::get(Fn->getContext(), attrkind));
+            }
+            else
+                Fn->addParamAttr(index, llvm::Attribute::get(Fn->getContext(), attributeandvalue.first, attributeandvalue.second));
+        }
+        if (auto atr = dyn_cast<LLVMRETAttr>(a)) {
+            std::pair<StringRef, StringRef> attributeandvalue = atr->getAttrName().split('=');
+            unsigned index = llvm::AttributeList::ReturnIndex;
+            llvm::Attribute::AttrKind attrkind = llvm::Attribute::parseAttrKind(attributeandvalue.first);
+            if (attrkind != llvm::Attribute::None) {
+                assert(attributeandvalue.second.size() == 0);
+                Fn->addParamAttr(index, llvm::Attribute::get(Fn->getContext(), attrkind));
+            }
+            else
+                Fn->addParamAttr(index, llvm::Attribute::get(Fn->getContext(), attributeandvalue.first, attributeandvalue.second));
+        }
+    }
+  }
+
   // Apply xray attributes to the function (as a string, for now)
   if (D) {
     if (const auto *XRayAttr = D->getAttr<XRayInstrumentAttr>()) {
Index: clang/lib/CodeGen/CodeGenAction.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenAction.cpp
+++ clang/lib/CodeGen/CodeGenAction.cpp
@@ -369,6 +369,8 @@
                                  unsigned DiagID);
     void
     OptimizationRemarkHandler(const llvm::DiagnosticInfoOptimizationBase &D);
+    void OptimizationRemarkHandler(
+        const llvm::OptimizationRemarkAnnotation &D);
     void OptimizationRemarkHandler(
         const llvm::OptimizationRemarkAnalysisFPCommute &D);
     void OptimizationRemarkHandler(
@@ -681,6 +683,27 @@
   }
 }
 
+void BackendConsumer::OptimizationRemarkHandler(
+    const llvm::OptimizationRemarkAnnotation &D) {
+  // Optimization analysis remarks are active if the pass name is set to
+  // llvm::DiagnosticInfo::AlwasyPrint or if the -Rpass-analysis flag has a
+  // regular expression that matches the name of the pass name in \p D.
+
+  StringRef Filename;
+  unsigned Line, Column;
+  bool BadDebugInfo = false;
+  FullSourceLoc Loc =
+      getBestLocationFromDebugLoc(D, BadDebugInfo, Filename, Line, Column);
+
+  std::string Msg;
+  raw_string_ostream MsgStream(Msg);
+  MsgStream << D.getMsg(); 
+
+  Diags.Report(Loc, diag::remark_fe_backend_optimization_remark_annotation)
+      << MsgStream.str()
+      ;
+}
+
 void BackendConsumer::OptimizationRemarkHandler(
     const llvm::OptimizationRemarkAnalysisFPCommute &D) {
   // Optimization analysis remarks are active if the pass name is set to
@@ -751,6 +774,11 @@
     // handler. There is no generic way of emitting them.
     OptimizationRemarkHandler(cast<OptimizationRemarkAnalysis>(DI));
     return;
+  case llvm::DK_OptimizationRemarkAnnotation:
+    // Optimization remarks are always handled completely by this
+    // handler. There is no generic way of emitting them.
+    OptimizationRemarkHandler(cast<OptimizationRemarkAnnotation>(DI));
+    return;
   case llvm::DK_OptimizationRemarkAnalysisFPCommute:
     // Optimization remarks are always handled completely by this
     // handler. There is no generic way of emitting them.
Index: clang/include/clang/Basic/DiagnosticGroups.td
===================================================================
--- clang/include/clang/Basic/DiagnosticGroups.td
+++ clang/include/clang/Basic/DiagnosticGroups.td
@@ -1013,6 +1013,7 @@
 def BackendFrameLargerThanEQ : DiagGroup<"frame-larger-than=">;
 def BackendPlugin : DiagGroup<"backend-plugin">;
 def RemarkBackendPlugin : DiagGroup<"remark-backend-plugin">;
+def BackendOptimizationRemarkAnnotation : DiagGroup<"annotation">;
 def BackendOptimizationRemark : DiagGroup<"pass">;
 def BackendOptimizationRemarkMissed : DiagGroup<"pass-missed">;
 def BackendOptimizationRemarkAnalysis : DiagGroup<"pass-analysis">;
Index: clang/include/clang/Basic/DiagnosticFrontendKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticFrontendKinds.td
+++ clang/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -44,6 +44,8 @@
     InGroup<BackendOptimizationRemarkMissed>;
 def remark_fe_backend_optimization_remark_analysis : Remark<"%0">, BackendInfo,
     InGroup<BackendOptimizationRemarkAnalysis>;
+def remark_fe_backend_optimization_remark_annotation : Remark<"%0">, BackendInfo,
+    InGroup<BackendOptimizationRemarkAnnotation>;
 def remark_fe_backend_optimization_remark_analysis_fpcommute : Remark<"%0; "
     "allow reordering by specifying '#pragma clang loop vectorize(enable)' "
     "before the loop or by providing the compiler option '-ffast-math'.">,
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>;
 
@@ -1631,6 +1634,24 @@
   let Documentation = [AllocAlignDocs];
 }
 
+def LLVMFN : InheritableAttr {
+  let Spellings = [GCC<"LLVMFN">];
+  let Args = [StringArgument<"AttrName">];
+  let Documentation = [Undocumented];
+}
+
+def LLVMARG : InheritableAttr {
+  let Spellings = [GCC<"LLVMARG">];
+  let Args = [ParamOrParamIdxArgument<"ParamIndex">, StringArgument<"AttrName">];
+  let Documentation = [Undocumented];
+}
+
+def LLVMRET : InheritableAttr {
+  let Spellings = [GCC<"LLVMRET">];
+  let Args = [StringArgument<"AttrName">];
+  let Documentation = [Undocumented];
+}
+
 def NoReturn : InheritableAttr {
   let Spellings = [GCC<"noreturn">, Declspec<"noreturn">];
   // FIXME: Does GCC allow this on the function instead?
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to