Bring llvm.annotation* intrinsics support back to where it was in llvm-gcc: can

annotate global, local variables, struct fields, or arbitrary statements (using
the __builtin_annotation), rdar://8037476.

llvm-svn: 139423
This commit is contained in:
Julien Lerouge 2011-09-09 22:41:49 +00:00
parent 5bfb0e0a85
commit 5a6b6987dc
21 changed files with 401 additions and 88 deletions

View 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">];
}

View 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

View 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<

View 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

View 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);
}

View 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);

View 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;
}

View 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
//===--------------------------------------------------------------------===//

View 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) {

View 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);

View 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

View 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();

View 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()));
}

View 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 */

View File

@ -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 }]

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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"

View File

@ -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 }

View File

@ -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;
}

View 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");
}