]> granicus.if.org Git - clang/commitdiff
Bring llvm.annotation* intrinsics support back to where it was in llvm-gcc: can
authorJulien Lerouge <jlerouge@apple.com>
Fri, 9 Sep 2011 22:41:49 +0000 (22:41 +0000)
committerJulien Lerouge <jlerouge@apple.com>
Fri, 9 Sep 2011 22:41:49 +0000 (22:41 +0000)
annotate global, local variables, struct fields, or arbitrary statements (using
the __builtin_annotation), rdar://8037476.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@139423 91177308-0d34-0410-b5e6-96231b3b80d8

21 files changed:
include/clang/Basic/Attr.td
include/clang/Basic/Builtins.def
include/clang/Basic/DiagnosticSemaKinds.td
lib/CodeGen/CGBuiltin.cpp
lib/CodeGen/CGDecl.cpp
lib/CodeGen/CGExpr.cpp
lib/CodeGen/CodeGenFunction.cpp
lib/CodeGen/CodeGenFunction.h
lib/CodeGen/CodeGenModule.cpp
lib/CodeGen/CodeGenModule.h
lib/Sema/SemaChecking.cpp
lib/Sema/SemaDecl.cpp
lib/Sema/SemaDeclAttr.cpp
test/CodeGen/2007-06-15-AnnotateAttribute.c
test/CodeGen/annotate.c [deleted file]
test/CodeGen/annotations-builtin.c [new file with mode: 0644]
test/CodeGen/annotations-field.c [new file with mode: 0644]
test/CodeGen/annotations-global.c [new file with mode: 0644]
test/CodeGen/annotations-loc.c [new file with mode: 0644]
test/CodeGen/annotations-var.c [new file with mode: 0644]
test/Sema/annotate.c

index d2de30a439b18f73bd10b04a2f48d501c339cd7b..9289bd286edacabd3b81e9a4699c2ab66c352abb 100644 (file)
@@ -131,7 +131,7 @@ def AnalyzerNoReturn : InheritableAttr {
   let Spellings = ["analyzer_noreturn"];
 }
 
-def Annotate : InheritableAttr {
+def Annotate : InheritableParamAttr {
   let Spellings = ["annotate"];
   let Args = [StringArgument<"Annotation">];
 }
index b8916d23e0e8b27dfbf93c10ab5394a3b747a51d..eb5c604294b31bc495b9577384a0fd144149b895 100644 (file)
@@ -741,5 +741,8 @@ LIBBUILTIN(_Block_object_assign, "vv*vC*iC", "f", "Blocks.h", ALL_LANGUAGES)
 LIBBUILTIN(_Block_object_dispose, "vvC*iC", "f", "Blocks.h", ALL_LANGUAGES)
 // FIXME: Also declare NSConcreteGlobalBlock and NSConcreteStackBlock.
 
+// Annotation function
+BUILTIN(__builtin_annotation, "UiUicC*", "nc")
+
 #undef BUILTIN
 #undef LIBBUILTIN
index 49d7bed09ac44055cb369696db7ecc691538536e..bd18b2f63f1e48d3807770f53ca814c705bc7d12 100644 (file)
@@ -4420,6 +4420,9 @@ def err_return_in_block_expression : Error<
 def err_block_returning_array_function : Error<
   "block cannot return %select{array|function}0 type %1">;
 
+// Builtin annotation string.
+def err_builtin_annotation_not_string_constant : Error<
+  "__builtin_annotation requires a non wide string constant">;
 
 // CFString checking
 def err_cfstring_literal_not_string_constant : Error<
index 642bf15e1b47306ff79800b663e4cbfcec61e53d..18c2bd3fe7a9b262f156555be1ea264308dfee73 100644 (file)
@@ -991,6 +991,17 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
     Value *Result = Builder.CreateICmpSLT(BCArg, ZeroCmp);
     return RValue::get(Builder.CreateZExt(Result, ConvertType(E->getType())));
   }
+  case Builtin::BI__builtin_annotation: {
+    llvm::Value *AnnVal = EmitScalarExpr(E->getArg(0));
+    llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::annotation,
+                                      AnnVal->getType());
+
+    // Get the annotation string, go through casts. Sema requires this to be a
+    // non-wide string literal, potentially casted, so the cast<> is safe.
+    const Expr *AnnotationStrExpr = E->getArg(1)->IgnoreParenCasts();
+    llvm::StringRef Str = cast<StringLiteral>(AnnotationStrExpr)->getString();
+    return RValue::get(EmitAnnotationCall(F, AnnVal, Str, E->getExprLoc()));
+  }
   }
 
   // If this is an alias for a libm function (e.g. __builtin_sin) turn it into
index 5fa99a513adcd653b0005c8a5a0545c15e5208d2..9ecc72781cfaaf3324c4a4d65617fff5467a58eb 100644 (file)
@@ -271,13 +271,8 @@ void CodeGenFunction::EmitStaticVarDecl(const VarDecl &D,
 
   GV->setAlignment(getContext().getDeclAlign(&D).getQuantity());
 
-  // FIXME: Merge attribute handling.
-  if (const AnnotateAttr *AA = D.getAttr<AnnotateAttr>()) {
-    SourceManager &SM = CGM.getContext().getSourceManager();
-    llvm::Constant *Ann =
-      CGM.EmitAnnotateAttr(GV, AA, SM.getExpansionLineNumber(D.getLocation()));
-    CGM.AddAnnotation(Ann);
-  }
+  if (D.hasAttr<AnnotateAttr>())
+    CGM.AddGlobalAnnotations(&D, GV);
 
   if (const SectionAttr *SA = D.getAttr<SectionAttr>())
     GV->setSection(SA->getName());
@@ -853,6 +848,9 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
         DI->EmitDeclareOfAutoVariable(&D, DeclPtr, Builder);
     }
 
+  if (D.hasAttr<AnnotateAttr>())
+      EmitVarAnnotations(&D, emission.Address);
+
   return emission;
 }
 
@@ -1502,4 +1500,7 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, llvm::Value *Arg,
   // Emit debug info for param declaration.
   if (CGDebugInfo *DI = getDebugInfo())
     DI->EmitDeclareOfArgVariable(&D, DeclPtr, ArgNo, Builder);
+
+  if (D.hasAttr<AnnotateAttr>())
+      EmitVarAnnotations(&D, DeclPtr);
 }
index daaf7a5887148cf286d5de60e090668f8b767ebe..7ae95331ad5f844da6b69fa83d77cb934ef1fe57 100644 (file)
@@ -1875,6 +1875,9 @@ LValue CodeGenFunction::EmitLValueForField(llvm::Value *baseAddr,
                                          CGM.getTypes().ConvertTypeForMem(type),
                                          field->getName());
 
+  if (field->hasAttr<AnnotateAttr>())
+    addr = EmitFieldAnnotations(field, addr);
+
   unsigned alignment = getContext().getDeclAlign(field).getQuantity();
   LValue LV = MakeAddrLValue(addr, type, alignment);
   LV.getQuals().addCVRQualifiers(cvr);
index a16f10e6541e229defa1e6e8fd908e2830b69ea2..b4b2eb16adabeb15014b952439417369126015db 100644 (file)
@@ -1018,3 +1018,50 @@ void CodeGenFunction::unprotectFromPeepholes(PeepholeProtection protection) {
   // In theory, we could try to duplicate the peepholes now, but whatever.
   protection.Inst->eraseFromParent();
 }
+
+llvm::Value *CodeGenFunction::EmitAnnotationCall(llvm::Value *AnnotationFn,
+                                                 llvm::Value *AnnotatedVal,
+                                                 llvm::StringRef AnnotationStr,
+                                                 SourceLocation Location) {
+  llvm::Value *Args[4] = {
+    AnnotatedVal,
+    Builder.CreateBitCast(CGM.EmitAnnotationString(AnnotationStr), Int8PtrTy),
+    Builder.CreateBitCast(CGM.EmitAnnotationUnit(Location), Int8PtrTy),
+    CGM.EmitAnnotationLineNo(Location)
+  };
+  return Builder.CreateCall(AnnotationFn, Args);
+}
+
+void CodeGenFunction::EmitVarAnnotations(const VarDecl *D, llvm::Value *V) {
+  assert(D->hasAttr<AnnotateAttr>() && "no annotate attribute");
+  // FIXME We create a new bitcast for every annotation because that's what
+  // llvm-gcc was doing.
+  for (specific_attr_iterator<AnnotateAttr>
+       ai = D->specific_attr_begin<AnnotateAttr>(),
+       ae = D->specific_attr_end<AnnotateAttr>(); ai != ae; ++ai)
+    EmitAnnotationCall(CGM.getIntrinsic(llvm::Intrinsic::var_annotation),
+                       Builder.CreateBitCast(V, CGM.Int8PtrTy, V->getName()),
+                       (*ai)->getAnnotation(), D->getLocation());
+}
+
+llvm::Value *CodeGenFunction::EmitFieldAnnotations(const FieldDecl *D,
+                                                   llvm::Value *V) {
+  assert(D->hasAttr<AnnotateAttr>() && "no annotate attribute");
+  llvm::Type *VTy = V->getType();
+  llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::ptr_annotation,
+                                    CGM.Int8PtrTy);
+
+  for (specific_attr_iterator<AnnotateAttr>
+       ai = D->specific_attr_begin<AnnotateAttr>(),
+       ae = D->specific_attr_end<AnnotateAttr>(); ai != ae; ++ai) {
+    // FIXME Always emit the cast inst so we can differentiate between
+    // annotation on the first field of a struct and annotation on the struct
+    // itself.
+    if (VTy != CGM.Int8PtrTy)
+      V = Builder.Insert(new llvm::BitCastInst(V, CGM.Int8PtrTy));
+    V = EmitAnnotationCall(F, V, (*ai)->getAnnotation(), D->getLocation());
+    V = Builder.CreateBitCast(V, VTy);
+  }
+
+  return V;
+}
index 36dcffcd4c02e55ab075745088caf658f7f2a7a5..702aca8aca730d70f4d521c95b3849299a8aafb6 100644 (file)
@@ -2271,6 +2271,23 @@ public:
 
   void EmitCXXThrowExpr(const CXXThrowExpr *E);
 
+  //===--------------------------------------------------------------------===//
+  //                         Annotations Emission
+  //===--------------------------------------------------------------------===//
+
+  /// Emit an annotation call (intrinsic or builtin).
+  llvm::Value *EmitAnnotationCall(llvm::Value *AnnotationFn,
+                                  llvm::Value *AnnotatedVal,
+                                  llvm::StringRef AnnotationStr,
+                                  SourceLocation Location);
+
+  /// Emit local annotations for the local variable V, declared by D.
+  void EmitVarAnnotations(const VarDecl *D, llvm::Value *V);
+
+  /// Emit field annotations for the given field & value. Returns the
+  /// annotation result.
+  llvm::Value *EmitFieldAnnotations(const FieldDecl *D, llvm::Value *V);
+
   //===--------------------------------------------------------------------===//
   //                             Internal Helpers
   //===--------------------------------------------------------------------===//
index 6df03c886feaf12a9d50b6992b40cca6055ffea9..67757a22c5fcb98ec36860f9ec8376eeb67a7ce9 100644 (file)
@@ -44,6 +44,8 @@
 using namespace clang;
 using namespace CodeGen;
 
+static const char AnnotationSection[] = "llvm.metadata";
+
 static CGCXXABI &createCXXABI(CodeGenModule &CGM) {
   switch (CGM.getContext().getTargetInfo().getCXXABI()) {
   case CXXABI_ARM: return *CreateARMCXXABI(CGM);
@@ -131,7 +133,7 @@ void CodeGenModule::Release() {
       AddGlobalCtor(ObjCInitFunction);
   EmitCtorList(GlobalCtors, "llvm.global_ctors");
   EmitCtorList(GlobalDtors, "llvm.global_dtors");
-  EmitAnnotations();
+  EmitGlobalAnnotations();
   EmitLLVMUsed();
 
   SimplifyPersonality();
@@ -382,22 +384,6 @@ void CodeGenModule::EmitCtorList(const CtorList &Fns, const char *GlobalName) {
   }
 }
 
-void CodeGenModule::EmitAnnotations() {
-  if (Annotations.empty())
-    return;
-
-  // Create a new global variable for the ConstantStruct in the Module.
-  llvm::Constant *Array =
-  llvm::ConstantArray::get(llvm::ArrayType::get(Annotations[0]->getType(),
-                                                Annotations.size()),
-                           Annotations);
-  llvm::GlobalValue *gv =
-  new llvm::GlobalVariable(TheModule, Array->getType(), false,
-                           llvm::GlobalValue::AppendingLinkage, Array,
-                           "llvm.global.annotations");
-  gv->setSection("llvm.metadata");
-}
-
 llvm::GlobalValue::LinkageTypes
 CodeGenModule::getFunctionLinkage(const FunctionDecl *D) {
   GVALinkage Linkage = getContext().GetGVALinkageForFunction(D);
@@ -642,54 +628,78 @@ void CodeGenModule::EmitDeferred() {
   }
 }
 
-/// EmitAnnotateAttr - Generate the llvm::ConstantStruct which contains the
-/// annotation information for a given GlobalValue.  The annotation struct is
-/// {i8 *, i8 *, i8 *, i32}.  The first field is a constant expression, the
-/// GlobalValue being annotated.  The second field is the constant string
-/// created from the AnnotateAttr's annotation.  The third field is a constant
-/// string containing the name of the translation unit.  The fourth field is
-/// the line number in the file of the annotated value declaration.
-///
-/// FIXME: this does not unique the annotation string constants, as llvm-gcc
-///        appears to.
-///
+void CodeGenModule::EmitGlobalAnnotations() {
+  if (Annotations.empty())
+    return;
+
+  // Create a new global variable for the ConstantStruct in the Module.
+  llvm::Constant *Array = llvm::ConstantArray::get(llvm::ArrayType::get(
+    Annotations[0]->getType(), Annotations.size()), Annotations);
+  llvm::GlobalValue *gv = new llvm::GlobalVariable(getModule(),
+    Array->getType(), false, llvm::GlobalValue::AppendingLinkage, Array,
+    "llvm.global.annotations");
+  gv->setSection(AnnotationSection);
+}
+
+llvm::Constant *CodeGenModule::EmitAnnotationString(llvm::StringRef Str) {
+  llvm::StringMap<llvm::Constant*>::iterator i = AnnotationStrings.find(Str);
+  if (i != AnnotationStrings.end())
+    return i->second;
+
+  // Not found yet, create a new global.
+  llvm::Constant *s = llvm::ConstantArray::get(getLLVMContext(), Str, true);
+  llvm::GlobalValue *gv = new llvm::GlobalVariable(getModule(), s->getType(),
+    true, llvm::GlobalValue::PrivateLinkage, s, ".str");
+  gv->setSection(AnnotationSection);
+  gv->setUnnamedAddr(true);
+  AnnotationStrings[Str] = gv;
+  return gv;
+}
+
+llvm::Constant *CodeGenModule::EmitAnnotationUnit(SourceLocation Loc) {
+  SourceManager &SM = getContext().getSourceManager();
+  PresumedLoc PLoc = SM.getPresumedLoc(Loc);
+  if (PLoc.isValid())
+    return EmitAnnotationString(PLoc.getFilename());
+  return EmitAnnotationString(SM.getBufferName(Loc));
+}
+
+llvm::Constant *CodeGenModule::EmitAnnotationLineNo(SourceLocation L) {
+  SourceManager &SM = getContext().getSourceManager();
+  PresumedLoc PLoc = SM.getPresumedLoc(L);
+  unsigned LineNo = PLoc.isValid() ? PLoc.getLine() :
+    SM.getExpansionLineNumber(L);
+  return llvm::ConstantInt::get(Int32Ty, LineNo);
+}
+
 llvm::Constant *CodeGenModule::EmitAnnotateAttr(llvm::GlobalValue *GV,
                                                 const AnnotateAttr *AA,
-                                                unsigned LineNo) {
-  llvm::Module *M = &getModule();
-
-  // get [N x i8] constants for the annotation string, and the filename string
-  // which are the 2nd and 3rd elements of the global annotation structure.
-  llvm::Type *SBP = llvm::Type::getInt8PtrTy(VMContext);
-  llvm::Constant *anno = llvm::ConstantArray::get(VMContext,
-                                                  AA->getAnnotation(), true);
-  llvm::Constant *unit = llvm::ConstantArray::get(VMContext,
-                                                  M->getModuleIdentifier(),
-                                                  true);
-
-  // Get the two global values corresponding to the ConstantArrays we just
-  // created to hold the bytes of the strings.
-  llvm::GlobalValue *annoGV =
-    new llvm::GlobalVariable(*M, anno->getType(), false,
-                             llvm::GlobalValue::PrivateLinkage, anno,
-                             GV->getName());
-  // translation unit name string, emitted into the llvm.metadata section.
-  llvm::GlobalValue *unitGV =
-    new llvm::GlobalVariable(*M, unit->getType(), false,
-                             llvm::GlobalValue::PrivateLinkage, unit,
-                             ".str");
-  unitGV->setUnnamedAddr(true);
+                                                SourceLocation L) {
+  // Get the globals for file name, annotation, and the line number.
+  llvm::Constant *AnnoGV = EmitAnnotationString(AA->getAnnotation()),
+                 *UnitGV = EmitAnnotationUnit(L),
+                 *LineNoCst = EmitAnnotationLineNo(L);
 
   // Create the ConstantStruct for the global annotation.
   llvm::Constant *Fields[4] = {
-    llvm::ConstantExpr::getBitCast(GV, SBP),
-    llvm::ConstantExpr::getBitCast(annoGV, SBP),
-    llvm::ConstantExpr::getBitCast(unitGV, SBP),
-    llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), LineNo)
+    llvm::ConstantExpr::getBitCast(GV, Int8PtrTy),
+    llvm::ConstantExpr::getBitCast(AnnoGV, Int8PtrTy),
+    llvm::ConstantExpr::getBitCast(UnitGV, Int8PtrTy),
+    LineNoCst
   };
   return llvm::ConstantStruct::getAnon(Fields);
 }
 
+void CodeGenModule::AddGlobalAnnotations(const ValueDecl *D,
+                                         llvm::GlobalValue *GV) {
+  assert(D->hasAttr<AnnotateAttr>() && "no annotate attribute");
+  // Get the struct elements for these annotations.
+  for (specific_attr_iterator<AnnotateAttr>
+       ai = D->specific_attr_begin<AnnotateAttr>(),
+       ae = D->specific_attr_end<AnnotateAttr>(); ai != ae; ++ai)
+    Annotations.push_back(EmitAnnotateAttr(GV, *ai, D->getLocation()));
+}
+
 bool CodeGenModule::MayDeferGeneration(const ValueDecl *Global) {
   // Never defer when EmitAllDecls is specified.
   if (Features.EmitAllDecls)
@@ -1297,11 +1307,8 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
     cast<llvm::GlobalValue>(Entry)->eraseFromParent();
   }
 
-  if (const AnnotateAttr *AA = D->getAttr<AnnotateAttr>()) {
-    SourceManager &SM = Context.getSourceManager();
-    AddAnnotation(EmitAnnotateAttr(
-        GV, AA, SM.getExpansionLineNumber(D->getLocation())));
-  }
+  if (D->hasAttr<AnnotateAttr>())
+    AddGlobalAnnotations(D, GV);
 
   GV->setInitializer(Init);
 
@@ -1530,6 +1537,8 @@ void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD) {
     AddGlobalCtor(Fn, CA->getPriority());
   if (const DestructorAttr *DA = D->getAttr<DestructorAttr>())
     AddGlobalDtor(Fn, DA->getPriority());
+  if (D->hasAttr<AnnotateAttr>())
+    AddGlobalAnnotations(D, Fn);
 }
 
 void CodeGenModule::EmitAliasDefinition(GlobalDecl GD) {
index 3e5de655abae3fe61ad11603b8d2f1e77f04f6b5..7d0d95141ab216dffaa62ab711bf1902e4d9757c 100644 (file)
@@ -260,8 +260,12 @@ class CodeGenModule : public CodeGenTypeCache {
   llvm::DenseMap<GlobalDecl, StringRef> MangledDeclNames;
   llvm::BumpPtrAllocator MangledNamesAllocator;
   
+  /// Global annotations.
   std::vector<llvm::Constant*> Annotations;
 
+  /// Map used to get unique annotation strings.
+  llvm::StringMap<llvm::Constant*> AnnotationStrings;
+
   llvm::StringMap<llvm::Constant*> CFConstantStringMap;
   llvm::StringMap<llvm::GlobalVariable*> ConstantStringMap;
   llvm::DenseMap<const Decl*, llvm::Value*> StaticLocalDeclMap;
@@ -598,8 +602,6 @@ public:
   /// metadata global.
   void AddUsedGlobal(llvm::GlobalValue *GV);
 
-  void AddAnnotation(llvm::Constant *C) { Annotations.push_back(C); }
-
   /// AddCXXDtorEntry - Add a destructor and object to add to the C++ global
   /// destructor function.
   void AddCXXDtorEntry(llvm::Constant *DtorFn, llvm::Constant *Object) {
@@ -643,9 +645,6 @@ public:
   /// but not always, an LLVM null constant.
   llvm::Constant *EmitNullConstant(QualType T);
 
-  llvm::Constant *EmitAnnotateAttr(llvm::GlobalValue *GV,
-                                   const AnnotateAttr *AA, unsigned LineNo);
-
   /// Error - Emit a general error that something can't be done.
   void Error(SourceLocation loc, StringRef error);
 
@@ -733,6 +732,33 @@ public:
   
   std::vector<const CXXRecordDecl*> DeferredVTables;
 
+  /// Emit all the global annotations.
+  void EmitGlobalAnnotations();
+
+  /// Emit an annotation string.
+  llvm::Constant *EmitAnnotationString(llvm::StringRef Str);
+
+  /// Emit the annotation's translation unit.
+  llvm::Constant *EmitAnnotationUnit(SourceLocation Loc);
+
+  /// Emit the annotation line number.
+  llvm::Constant *EmitAnnotationLineNo(SourceLocation L);
+
+  /// EmitAnnotateAttr - Generate the llvm::ConstantStruct which contains the
+  /// annotation information for a given GlobalValue. The annotation struct is
+  /// {i8 *, i8 *, i8 *, i32}. The first field is a constant expression, the
+  /// GlobalValue being annotated. The second field is the constant string
+  /// created from the AnnotateAttr's annotation. The third field is a constant
+  /// string containing the name of the translation unit. The fourth field is
+  /// the line number in the file of the annotated value declaration.
+  llvm::Constant *EmitAnnotateAttr(llvm::GlobalValue *GV,
+                                   const AnnotateAttr *AA,
+                                   SourceLocation L);
+
+  /// Add global annotations that are set on D, for the global GV. Those
+  /// annotations are emitted during finalization of the LLVM code.
+  void AddGlobalAnnotations(const ValueDecl *D, llvm::GlobalValue *GV);
+
 private:
   llvm::GlobalValue *GetGlobalValue(StringRef Ref);
 
@@ -818,8 +844,6 @@ private:
   /// suitable for use as a LLVM constructor or destructor array.
   void EmitCtorList(const CtorList &Fns, const char *GlobalName);
 
-  void EmitAnnotations(void);
-
   /// EmitFundamentalRTTIDescriptor - Emit the RTTI descriptors for the
   /// given type.
   void EmitFundamentalRTTIDescriptor(QualType Type);
index 68e25e7f4e5a48e218fac37c74c0ff58cdb7656b..f0dd68759812b40eb2e23de64eb5d51079950ba0 100644 (file)
@@ -88,6 +88,19 @@ static bool checkArgCount(Sema &S, CallExpr *call, unsigned desiredArgCount) {
     << call->getArg(1)->getSourceRange();
 }
 
+/// CheckBuiltinAnnotationString - Checks that string argument to the builtin
+/// annotation is a non wide string literal.
+static bool CheckBuiltinAnnotationString(Sema &S, Expr *Arg) {
+  Arg = Arg->IgnoreParenCasts();
+  StringLiteral *Literal = dyn_cast<StringLiteral>(Arg);
+  if (!Literal || !Literal->isAscii()) {
+    S.Diag(Arg->getLocStart(), diag::err_builtin_annotation_not_string_constant)
+      << Arg->getSourceRange();
+    return true;
+  }
+  return false;
+}
+
 ExprResult
 Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
   ExprResult TheCallResult(Owned(TheCall));
@@ -184,6 +197,10 @@ Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
   case Builtin::BI__sync_lock_release:
   case Builtin::BI__sync_swap:
     return SemaBuiltinAtomicOverloaded(move(TheCallResult));
+  case Builtin::BI__builtin_annotation:
+    if (CheckBuiltinAnnotationString(*this, TheCall->getArg(1)))
+      return ExprError();
+    break;
   }
   
   // Since the target specific builtins for each arch overlap, only check those
@@ -640,7 +657,6 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) {
   return move(TheCallResult);
 }
 
-
 /// CheckObjCString - Checks that the argument to the builtin
 /// CFString constructor is correct
 /// Note: It might also make sense to do the UTF-16 conversion here (would
index 355378eded78e50372c36eddb710a2e7bea65d89..d6137e5dba388520c2818bb644c0928be5ff3cf5 100644 (file)
@@ -1461,8 +1461,14 @@ void Sema::MergeTypedefNameDecl(TypedefNameDecl *New, LookupResult &OldDecls) {
 static bool
 DeclHasAttr(const Decl *D, const Attr *A) {
   const OwnershipAttr *OA = dyn_cast<OwnershipAttr>(A);
+  const AnnotateAttr *Ann = dyn_cast<AnnotateAttr>(A);
   for (Decl::attr_iterator i = D->attr_begin(), e = D->attr_end(); i != e; ++i)
     if ((*i)->getKind() == A->getKind()) {
+      if (Ann) {
+        if (Ann->getAnnotation() == cast<AnnotateAttr>(*i)->getAnnotation())
+          return true;
+        continue;
+      }
       // FIXME: Don't hardcode this check
       if (OA && isa<OwnershipAttr>(*i))
         return OA->getOwnKind() == cast<OwnershipAttr>(*i)->getOwnKind();
index 624ac086db16cd81fbaf6c78fdb8294a8def0762..2f2e280f714d4b6d8de9c0aea637aa19afbe8c28 100644 (file)
@@ -2484,6 +2484,14 @@ static void handleAnnotateAttr(Sema &S, Decl *D, const AttributeList &Attr) {
     S.Diag(ArgExpr->getLocStart(), diag::err_attribute_not_string) <<"annotate";
     return;
   }
+
+  // Don't duplicate annotations that are already set.
+  for (specific_attr_iterator<AnnotateAttr>
+       i = D->specific_attr_begin<AnnotateAttr>(),
+       e = D->specific_attr_end<AnnotateAttr>(); i != e; ++i) {
+      if ((*i)->getAnnotation() == SE->getString())
+          return;
+  }
   D->addAttr(::new (S.Context) AnnotateAttr(Attr.getLoc(), S.Context,
                                             SE->getString()));
 }
index 324b975575535a6a67c38e581a95970e633b181b..a51400288c2b3649c092417e98b246d092ad720a 100644 (file)
@@ -1,7 +1,6 @@
 // RUN: %clang_cc1 -emit-llvm %s -o - | grep llvm.global.annotations
 // RUN: %clang_cc1 -emit-llvm %s -o - | grep llvm.var.annotation | count 3
 
-// XFAIL: *
 #include <stdio.h>
 
 /* Global variable with attribute */
diff --git a/test/CodeGen/annotate.c b/test/CodeGen/annotate.c
deleted file mode 100644 (file)
index 9ed187d..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s
-
-__attribute((annotate("foo"))) char foo;
-void a(char *a) { 
-  __attribute__((annotate("bar"))) static char bar;
-}
-
-// CHECK: private unnamed_addr global
-// CHECK: private unnamed_addr global
-// CHECK: @llvm.global.annotations = appending global [2 x { i8*, i8*, i8*, i32 }]
diff --git a/test/CodeGen/annotations-builtin.c b/test/CodeGen/annotations-builtin.c
new file mode 100644 (file)
index 0000000..42421a0
--- /dev/null
@@ -0,0 +1,52 @@
+// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s
+// END.
+
+static long long llfoo;
+static int intfoo;
+static short shortfoo;
+static char charfoo;
+
+// CHECK: private unnamed_addr constant [13 x i8] {{.*}}annotation_a{{.*}} section "llvm.metadata"
+// CHECK-NOT: {{.*}}annotation_a{{.*}}
+
+static int foo(int a) {
+    return a + 1;
+}
+
+int main(int argc, char **argv) {
+    char barray[16];
+    char *b = (char *) __builtin_annotation((int)barray, "annotation_a");
+// CHECK: ptrtoint i8* {{.*}} to i32
+// CHECK-NEXT: call i32 @llvm.annotation.i32
+// CHECK: inttoptr {{.*}} to i8*
+
+    int call = __builtin_annotation(foo(argc), "annotation_a");
+// CHECK: call {{.*}} @foo
+// CHECK: call i32 @llvm.annotation.i32
+
+    long long lla = __builtin_annotation(llfoo, "annotation_a");
+// CHECK: trunc i64 {{.*}} to i32
+// CHECK-NEXT: call i32 @llvm.annotation.i32
+// CHECK-NEXT: zext i32 {{.*}} to i64
+
+    int inta = __builtin_annotation(intfoo, "annotation_a");
+// CHECK: load i32* @intfoo
+// CHECK-NEXT: call i32 @llvm.annotation.i32
+// CHECK-NEXT: store
+
+    short shorta =  __builtin_annotation(shortfoo, "annotation_a");
+// CHECK: sext i16 {{.*}} to i32
+// CHECK-NEXT: call i32 @llvm.annotation.i32
+// CHECK-NEXT: trunc i32 {{.*}} to i16
+
+    char chara = __builtin_annotation(charfoo, "annotation_a");
+// CHECK: sext i8 {{.*}} to i32
+// CHECK-NEXT: call i32 @llvm.annotation.i32
+// CHECK-NEXT: trunc i32 {{.*}} to i8
+//
+    char **arg = (char**) __builtin_annotation((int) argv, "annotation_a");
+// CHECK: ptrtoint i8** {{.*}} to
+// CHECK: call i32 @llvm.annotation.i32
+// CHECK: inttoptr {{.*}} to i8**
+    return 0;
+}
diff --git a/test/CodeGen/annotations-field.c b/test/CodeGen/annotations-field.c
new file mode 100644 (file)
index 0000000..6b44367
--- /dev/null
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s
+// END.
+
+// CHECK: private unnamed_addr constant [8 x i8] c"v_ann_{{.}}\00", section "llvm.metadata"
+// CHECK: private unnamed_addr constant [8 x i8] c"v_ann_{{.}}\00", section "llvm.metadata"
+
+struct foo {
+    int v __attribute__((annotate("v_ann_0"))) __attribute__((annotate("v_ann_1")));
+};
+
+static struct foo gf;
+
+int main(int argc, char **argv) {
+    struct foo f;
+    f.v = argc;
+// CHECK: getelementptr inbounds %struct.foo* %f, i32 0, i32 0
+// CHECK-NEXT: bitcast i32* {{.*}} to i8*
+// CHECK-NEXT: call i8* @llvm.ptr.annotation.p0i8({{.*}}str{{.*}}str{{.*}}i32 8)
+// CHECK-NEXT: bitcast i8* {{.*}} to i32*
+// CHECK-NEXT: bitcast i32* {{.*}} to i8*
+// CHECK-NEXT: call i8* @llvm.ptr.annotation.p0i8({{.*}}str{{.*}}str{{.*}}i32 8)
+// CHECK-NEXT: bitcast i8* {{.*}} to i32*
+    gf.v = argc;
+// CHECK: bitcast i32* getelementptr inbounds (%struct.foo* @gf, i32 0, i32 0) to i8*
+// CHECK-NEXT: call i8* @llvm.ptr.annotation.p0i8({{.*}}str{{.*}}str{{.*}}i32 8)
+    return 0;
+}
diff --git a/test/CodeGen/annotations-global.c b/test/CodeGen/annotations-global.c
new file mode 100644 (file)
index 0000000..2782525
--- /dev/null
@@ -0,0 +1,41 @@
+// RUN: %clang_cc1 %s -emit-llvm -o %t1
+// RUN: FileCheck --check-prefix=FOO %s < %t1
+// RUN: FileCheck --check-prefix=A %s < %t1
+// RUN: FileCheck --check-prefix=BAR %s < %t1
+// RUN: FileCheck --check-prefix=FOOS %s < %t1
+// END.
+
+static __attribute((annotate("sfoo_0"))) __attribute((annotate("sfoo_1"))) char sfoo;
+__attribute((annotate("foo_0"))) __attribute((annotate("foo_1"))) char foo;
+
+void __attribute((annotate("ann_a_0"))) __attribute((annotate("ann_a_1"))) __attribute((annotate("ann_a_2"))) __attribute((annotate("ann_a_3"))) a(char *a);
+void __attribute((annotate("ann_a_0"))) __attribute((annotate("ann_a_1"))) a(char *a) {
+  __attribute__((annotate("bar_0"))) __attribute__((annotate("bar_1"))) static char bar;
+  sfoo = 0;
+}
+
+// FOOS: target triple
+// FOOS: private unnamed_addr constant [7 x i8] c"sfoo_{{.}}\00", section "llvm.metadata"
+// FOOS: private unnamed_addr constant [7 x i8] c"sfoo_{{.}}\00", section "llvm.metadata"
+// FOOS-NOT: sfoo_
+// FOOS: @llvm.global.annotations = appending global [10 x { i8*, i8*, i8*, i32 }] {{.*}}i8* @sfoo{{.*}}i8* @sfoo{{.*}}, section "llvm.metadata"
+
+// FOO: target triple
+// FOO: private unnamed_addr constant [6 x i8] c"foo_{{.}}\00", section "llvm.metadata"
+// FOO: private unnamed_addr constant [6 x i8] c"foo_{{.}}\00", section "llvm.metadata"
+// FOO-NOT: foo_
+// FOO: @llvm.global.annotations = appending global [10 x { i8*, i8*, i8*, i32 }] {{.*}}i8* @foo{{.*}}i8* @foo{{.*}}, section "llvm.metadata"
+
+// A: target triple
+// A: private unnamed_addr constant [8 x i8] c"ann_a_{{.}}\00", section "llvm.metadata"
+// A: private unnamed_addr constant [8 x i8] c"ann_a_{{.}}\00", section "llvm.metadata"
+// A: private unnamed_addr constant [8 x i8] c"ann_a_{{.}}\00", section "llvm.metadata"
+// A: private unnamed_addr constant [8 x i8] c"ann_a_{{.}}\00", section "llvm.metadata"
+// A-NOT: ann_a_
+// A: @llvm.global.annotations = appending global [10 x { i8*, i8*, i8*, i32 }] {{.*}}i8* bitcast (void (i8*)* @a to i8*){{.*}}i8* bitcast (void (i8*)* @a to i8*){{.*}}i8* bitcast (void (i8*)* @a to i8*){{.*}}i8* bitcast (void (i8*)* @a to i8*){{.*}}, section "llvm.metadata"
+
+// BAR: target triple
+// BAR: private unnamed_addr constant [6 x i8] c"bar_{{.}}\00", section "llvm.metadata"
+// BAR: private unnamed_addr constant [6 x i8] c"bar_{{.}}\00", section "llvm.metadata"
+// BAR-NOT: bar_
+// BAR: @llvm.global.annotations = appending global [10 x { i8*, i8*, i8*, i32 }] {{.*}}i8* @a.bar{{.*}}i8* @a.bar{{.*}}, section "llvm.metadata"
diff --git a/test/CodeGen/annotations-loc.c b/test/CodeGen/annotations-loc.c
new file mode 100644 (file)
index 0000000..4644f0e
--- /dev/null
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s
+// END.
+# 1 "t.c"
+# 1 "<built-in>"
+# 1 "<command-line>"
+# 1 "t.c"
+int __attribute((annotate("foo"))) foo(void) { return 0; }
+
+// CHECK: private unnamed_addr constant [4 x i8] c"t.c\00"
+// CHECK: @llvm.global.annotations = {{.*}}, i32 1 }
diff --git a/test/CodeGen/annotations-var.c b/test/CodeGen/annotations-var.c
new file mode 100644 (file)
index 0000000..97a10ac
--- /dev/null
@@ -0,0 +1,43 @@
+// RUN: %clang_cc1 -emit-llvm -o %t1 %s
+// RUN: FileCheck --check-prefix=LOCAL %s < %t1
+// RUN: FileCheck --check-prefix=UNDEF %s < %t1
+// RUN: FileCheck --check-prefix=PARAM %s < %t1
+// END.
+
+// LOCAL: private unnamed_addr constant [15 x i8] c"localvar_ann_{{.}}\00", section "llvm.metadata"
+// LOCAL: private unnamed_addr constant [15 x i8] c"localvar_ann_{{.}}\00", section "llvm.metadata"
+
+// UNDEF: private unnamed_addr constant [15 x i8] c"undefvar_ann_0\00", section "llvm.metadata"
+
+// PARAM: private unnamed_addr constant [12 x i8] c"param_ann_{{.}}\00", section "llvm.metadata"
+// PARAM: private unnamed_addr constant [12 x i8] c"param_ann_{{.}}\00", section "llvm.metadata"
+// PARAM: private unnamed_addr constant [12 x i8] c"param_ann_{{.}}\00", section "llvm.metadata"
+// PARAM: private unnamed_addr constant [12 x i8] c"param_ann_{{.}}\00", section "llvm.metadata"
+
+int foo(int v __attribute__((annotate("param_ann_2"))) __attribute__((annotate("param_ann_3"))));
+int foo(int v __attribute__((annotate("param_ann_0"))) __attribute__((annotate("param_ann_1")))) {
+    return v + 1;
+// PARAM: define {{.*}}@foo
+// PARAM:  bitcast i32* %v.addr to i8*
+// PARAM-NEXT: call void @llvm.var.annotation(
+// PARAM-NEXT: bitcast i32* %v.addr to i8*
+// PARAM-NEXT: call void @llvm.var.annotation(
+// PARAM-NEXT: bitcast i32* %v.addr to i8*
+// PARAM-NEXT: call void @llvm.var.annotation(
+// PARAM-NEXT: bitcast i32* %v.addr to i8*
+// PARAM-NEXT: call void @llvm.var.annotation(
+}
+
+int main(int argc, char **argv) {
+    int localvar __attribute__((annotate("localvar_ann_0"))) __attribute__((annotate("localvar_ann_1"))) = 3;
+// LOCAL: %localvar1 = bitcast i32* %localvar to i8*
+// LOCAL-NEXT: call void @llvm.var.annotation(i8* %localvar1, i8* getelementptr inbounds ([15 x i8]* @{{.*}}), i8* getelementptr inbounds ({{.*}}), i32 32)
+// LOCAL-NEXT: %localvar2 = bitcast i32* %localvar to i8*
+// LOCAL-NEXT: call void @llvm.var.annotation(i8* %localvar2, i8* getelementptr inbounds ([15 x i8]* @{{.*}}), i8* getelementptr inbounds ({{.*}}), i32 32)
+    int undefvar __attribute__((annotate("undefvar_ann_0")));
+// UNDEF: %undefvar3 = bitcast i32* %undefvar to i8*
+// UNDEF-NEXT: call void @llvm.var.annotation(i8* %undefvar3, i8* getelementptr inbounds ([15 x i8]* @{{.*}}), i8* getelementptr inbounds ({{.*}}), i32 37)
+    localvar += argc;
+    undefvar = localvar;
+    return undefvar + localvar;
+}
index 6f81491f1ffa48a03c52fd4da6046233b648d457..5b2727752bbd5aafe77c37d805e912fb8ca6f7a2 100644 (file)
@@ -4,4 +4,7 @@ void __attribute__((annotate("foo"))) foo(float *a) {
   __attribute__((annotate("bar"))) int x;
   __attribute__((annotate(1))) int y; // expected-error {{argument to annotate attribute was not a string literal}}
   __attribute__((annotate("bar", 1))) int z; // expected-error {{attribute takes one argument}}
+  int u = __builtin_annotation(z, (char*) 0); // expected-error {{__builtin_annotation requires a non wide string constant}}
+  int v = __builtin_annotation(z, (char*) L"bar"); // expected-error {{__builtin_annotation requires a non wide string constant}}
+  int w = __builtin_annotation(z, "foo");
 }