mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-10-09 12:24:08 +00:00
[Annotation] Allows annotation to carry some additional constant arguments.
This allows using annotation in a much more contexts than it currently has. especially when annotation with template or constexpr. Reviewed By: aaron.ballman Differential Revision: https://reviews.llvm.org/D88645
This commit is contained in:
parent
8aa60f67dc
commit
d3205bbca3
@ -737,7 +737,7 @@ def AnalyzerNoReturn : InheritableAttr {
|
||||
|
||||
def Annotate : InheritableParamAttr {
|
||||
let Spellings = [Clang<"annotate">];
|
||||
let Args = [StringArgument<"Annotation">];
|
||||
let Args = [StringArgument<"Annotation">, VariadicExprArgument<"Args">];
|
||||
// Ensure that the annotate attribute can be used with
|
||||
// '#pragma clang attribute' even though it has no subject list.
|
||||
let PragmaAttributeSupport = 1;
|
||||
|
@ -2860,7 +2860,7 @@ def err_attribute_sizeless_type : Error<
|
||||
"%0 attribute cannot be applied to sizeless type %1">;
|
||||
def err_attribute_argument_n_type : Error<
|
||||
"%0 attribute requires parameter %1 to be %select{int or bool|an integer "
|
||||
"constant|a string|an identifier}2">;
|
||||
"constant|a string|an identifier|a constant expression}2">;
|
||||
def err_attribute_argument_type : Error<
|
||||
"%0 attribute requires %select{int or bool|an integer "
|
||||
"constant|a string|an identifier}1">;
|
||||
|
@ -1023,7 +1023,8 @@ enum AttributeArgumentNType {
|
||||
AANT_ArgumentIntOrBool,
|
||||
AANT_ArgumentIntegerConstant,
|
||||
AANT_ArgumentString,
|
||||
AANT_ArgumentIdentifier
|
||||
AANT_ArgumentIdentifier,
|
||||
AANT_ArgumentConstantExpr,
|
||||
};
|
||||
|
||||
/// These constants match the enumerated choices of
|
||||
@ -1058,6 +1059,31 @@ inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
|
||||
return DB;
|
||||
}
|
||||
|
||||
/// AttributeCommonInfo has a non-explicit constructor which takes an
|
||||
/// SourceRange as its only argument, this constructor has many uses so making
|
||||
/// it explicit is hard. This constructor causes ambiguity with
|
||||
/// DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, SourceRange R).
|
||||
/// We use SFINAE to disable any conversion and remove any ambiguity.
|
||||
template <typename ACI,
|
||||
typename std::enable_if_t<
|
||||
std::is_same<ACI, AttributeCommonInfo>::value, int> = 0>
|
||||
inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
|
||||
const ACI &CI) {
|
||||
DB.AddTaggedVal(reinterpret_cast<intptr_t>(CI.getAttrName()),
|
||||
DiagnosticsEngine::ak_identifierinfo);
|
||||
return DB;
|
||||
}
|
||||
|
||||
template <typename ACI,
|
||||
typename std::enable_if_t<
|
||||
std::is_same<ACI, AttributeCommonInfo>::value, int> = 0>
|
||||
inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
|
||||
const ACI* CI) {
|
||||
DB.AddTaggedVal(reinterpret_cast<intptr_t>(CI->getAttrName()),
|
||||
DiagnosticsEngine::ak_identifierinfo);
|
||||
return DB;
|
||||
}
|
||||
|
||||
} // namespace clang
|
||||
|
||||
#endif // LLVM_CLANG_SEMA_ATTRIBUTELIST_H
|
||||
|
@ -9987,6 +9987,10 @@ public:
|
||||
/// declaration.
|
||||
void AddAlignValueAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E);
|
||||
|
||||
/// AddAnnotationAttr - Adds an annotation Annot with Args arguments to D.
|
||||
void AddAnnotationAttr(Decl *D, const AttributeCommonInfo &CI,
|
||||
StringRef Annot, MutableArrayRef<Expr *> Args);
|
||||
|
||||
/// AddLaunchBoundsAttr - Adds a launch_bounds attribute to a particular
|
||||
/// declaration.
|
||||
void AddLaunchBoundsAttr(Decl *D, const AttributeCommonInfo &CI,
|
||||
|
@ -3403,7 +3403,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
|
||||
// non-wide string literal, potentially casted, so the cast<> is safe.
|
||||
const Expr *AnnotationStrExpr = E->getArg(1)->IgnoreParenCasts();
|
||||
StringRef Str = cast<StringLiteral>(AnnotationStrExpr)->getString();
|
||||
return RValue::get(EmitAnnotationCall(F, AnnVal, Str, E->getExprLoc()));
|
||||
return RValue::get(
|
||||
EmitAnnotationCall(F, AnnVal, Str, E->getExprLoc(), nullptr));
|
||||
}
|
||||
case Builtin::BI__builtin_addcb:
|
||||
case Builtin::BI__builtin_addcs:
|
||||
|
@ -2234,13 +2234,16 @@ void CodeGenFunction::emitAlignmentAssumption(llvm::Value *PtrValue,
|
||||
llvm::Value *CodeGenFunction::EmitAnnotationCall(llvm::Function *AnnotationFn,
|
||||
llvm::Value *AnnotatedVal,
|
||||
StringRef AnnotationStr,
|
||||
SourceLocation Location) {
|
||||
llvm::Value *Args[4] = {
|
||||
AnnotatedVal,
|
||||
Builder.CreateBitCast(CGM.EmitAnnotationString(AnnotationStr), Int8PtrTy),
|
||||
Builder.CreateBitCast(CGM.EmitAnnotationUnit(Location), Int8PtrTy),
|
||||
CGM.EmitAnnotationLineNo(Location)
|
||||
SourceLocation Location,
|
||||
const AnnotateAttr *Attr) {
|
||||
SmallVector<llvm::Value *, 5> Args = {
|
||||
AnnotatedVal,
|
||||
Builder.CreateBitCast(CGM.EmitAnnotationString(AnnotationStr), Int8PtrTy),
|
||||
Builder.CreateBitCast(CGM.EmitAnnotationUnit(Location), Int8PtrTy),
|
||||
CGM.EmitAnnotationLineNo(Location),
|
||||
};
|
||||
if (Attr)
|
||||
Args.push_back(CGM.EmitAnnotationArgs(Attr));
|
||||
return Builder.CreateCall(AnnotationFn, Args);
|
||||
}
|
||||
|
||||
@ -2251,7 +2254,7 @@ void CodeGenFunction::EmitVarAnnotations(const VarDecl *D, llvm::Value *V) {
|
||||
for (const auto *I : D->specific_attrs<AnnotateAttr>())
|
||||
EmitAnnotationCall(CGM.getIntrinsic(llvm::Intrinsic::var_annotation),
|
||||
Builder.CreateBitCast(V, CGM.Int8PtrTy, V->getName()),
|
||||
I->getAnnotation(), D->getLocation());
|
||||
I->getAnnotation(), D->getLocation(), I);
|
||||
}
|
||||
|
||||
Address CodeGenFunction::EmitFieldAnnotations(const FieldDecl *D,
|
||||
@ -2268,7 +2271,7 @@ Address CodeGenFunction::EmitFieldAnnotations(const FieldDecl *D,
|
||||
// itself.
|
||||
if (VTy != CGM.Int8PtrTy)
|
||||
V = Builder.CreateBitCast(V, CGM.Int8PtrTy);
|
||||
V = EmitAnnotationCall(F, V, I->getAnnotation(), D->getLocation());
|
||||
V = EmitAnnotationCall(F, V, I->getAnnotation(), D->getLocation(), I);
|
||||
V = Builder.CreateBitCast(V, VTy);
|
||||
}
|
||||
|
||||
|
@ -4326,7 +4326,8 @@ public:
|
||||
llvm::Value *EmitAnnotationCall(llvm::Function *AnnotationFn,
|
||||
llvm::Value *AnnotatedVal,
|
||||
StringRef AnnotationStr,
|
||||
SourceLocation Location);
|
||||
SourceLocation Location,
|
||||
const AnnotateAttr *Attr);
|
||||
|
||||
/// Emit local annotations for the local variable V, declared by D.
|
||||
void EmitVarAnnotations(const VarDecl *D, llvm::Value *V);
|
||||
|
@ -2341,13 +2341,48 @@ llvm::Constant *CodeGenModule::EmitAnnotationLineNo(SourceLocation L) {
|
||||
return llvm::ConstantInt::get(Int32Ty, LineNo);
|
||||
}
|
||||
|
||||
llvm::Constant *CodeGenModule::EmitAnnotationArgs(const AnnotateAttr *Attr) {
|
||||
ArrayRef<Expr *> Exprs = {Attr->args_begin(), Attr->args_size()};
|
||||
Exprs = Exprs.drop_front();
|
||||
if (Exprs.empty())
|
||||
return llvm::ConstantPointerNull::get(Int8PtrTy);
|
||||
|
||||
llvm::FoldingSetNodeID ID;
|
||||
for (Expr *E : Exprs) {
|
||||
ID.Add(cast<clang::ConstantExpr>(E)->getAPValueResult());
|
||||
}
|
||||
llvm::Constant *&Lookup = AnnotationArgs[ID.ComputeHash()];
|
||||
if (Lookup)
|
||||
return Lookup;
|
||||
|
||||
llvm::SmallVector<llvm::Constant *, 4> LLVMArgs;
|
||||
LLVMArgs.reserve(Exprs.size());
|
||||
ConstantEmitter ConstEmiter(*this);
|
||||
llvm::transform(Exprs, std::back_inserter(LLVMArgs), [&](const Expr *E) {
|
||||
const auto *CE = cast<clang::ConstantExpr>(E);
|
||||
return ConstEmiter.emitAbstract(CE->getBeginLoc(), CE->getAPValueResult(),
|
||||
CE->getType());
|
||||
});
|
||||
auto *Struct = llvm::ConstantStruct::getAnon(LLVMArgs);
|
||||
auto *GV = new llvm::GlobalVariable(getModule(), Struct->getType(), true,
|
||||
llvm::GlobalValue::PrivateLinkage, Struct,
|
||||
".args");
|
||||
GV->setSection(AnnotationSection);
|
||||
GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
|
||||
auto *Bitcasted = llvm::ConstantExpr::getBitCast(GV, Int8PtrTy);
|
||||
|
||||
Lookup = Bitcasted;
|
||||
return Bitcasted;
|
||||
}
|
||||
|
||||
llvm::Constant *CodeGenModule::EmitAnnotateAttr(llvm::GlobalValue *GV,
|
||||
const AnnotateAttr *AA,
|
||||
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);
|
||||
*LineNoCst = EmitAnnotationLineNo(L),
|
||||
*Args = EmitAnnotationArgs(AA);
|
||||
|
||||
llvm::Constant *ASZeroGV = GV;
|
||||
if (GV->getAddressSpace() != 0) {
|
||||
@ -2356,11 +2391,12 @@ llvm::Constant *CodeGenModule::EmitAnnotateAttr(llvm::GlobalValue *GV,
|
||||
}
|
||||
|
||||
// Create the ConstantStruct for the global annotation.
|
||||
llvm::Constant *Fields[4] = {
|
||||
llvm::ConstantExpr::getBitCast(ASZeroGV, Int8PtrTy),
|
||||
llvm::ConstantExpr::getBitCast(AnnoGV, Int8PtrTy),
|
||||
llvm::ConstantExpr::getBitCast(UnitGV, Int8PtrTy),
|
||||
LineNoCst
|
||||
llvm::Constant *Fields[] = {
|
||||
llvm::ConstantExpr::getBitCast(ASZeroGV, Int8PtrTy),
|
||||
llvm::ConstantExpr::getBitCast(AnnoGV, Int8PtrTy),
|
||||
llvm::ConstantExpr::getBitCast(UnitGV, Int8PtrTy),
|
||||
LineNoCst,
|
||||
Args,
|
||||
};
|
||||
return llvm::ConstantStruct::getAnon(Fields);
|
||||
}
|
||||
|
@ -413,6 +413,9 @@ private:
|
||||
/// Map used to get unique annotation strings.
|
||||
llvm::StringMap<llvm::Constant*> AnnotationStrings;
|
||||
|
||||
/// Used for uniquing of annotation arguments.
|
||||
llvm::DenseMap<unsigned, llvm::Constant *> AnnotationArgs;
|
||||
|
||||
llvm::StringMap<llvm::GlobalVariable *> CFConstantStringMap;
|
||||
|
||||
llvm::DenseMap<llvm::Constant *, llvm::GlobalVariable *> ConstantStringMap;
|
||||
@ -1241,6 +1244,9 @@ public:
|
||||
/// Emit the annotation line number.
|
||||
llvm::Constant *EmitAnnotationLineNo(SourceLocation L);
|
||||
|
||||
/// Emit additional args of the annotation.
|
||||
llvm::Constant *EmitAnnotationArgs(const AnnotateAttr *Attr);
|
||||
|
||||
/// 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
|
||||
|
@ -3682,20 +3682,68 @@ static void handleTransparentUnionAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
|
||||
RD->addAttr(::new (S.Context) TransparentUnionAttr(S.Context, AL));
|
||||
}
|
||||
|
||||
void Sema::AddAnnotationAttr(Decl *D, const AttributeCommonInfo &CI,
|
||||
StringRef Str, MutableArrayRef<Expr *> Args) {
|
||||
auto *Attr = AnnotateAttr::Create(Context, Str, Args.data(), Args.size(), CI);
|
||||
llvm::SmallVector<PartialDiagnosticAt, 8> Notes;
|
||||
for (unsigned Idx = 1; Idx < Attr->args_size(); Idx++) {
|
||||
Expr *&E = Attr->args_begin()[Idx];
|
||||
assert(E && "error are handled before");
|
||||
if (E->isValueDependent() || E->isTypeDependent())
|
||||
continue;
|
||||
|
||||
if (E->getType()->isArrayType())
|
||||
E = ImpCastExprToType(E, Context.getPointerType(E->getType()),
|
||||
clang::CK_ArrayToPointerDecay)
|
||||
.get();
|
||||
if (E->getType()->isFunctionType())
|
||||
E = ImplicitCastExpr::Create(Context,
|
||||
Context.getPointerType(E->getType()),
|
||||
clang::CK_FunctionToPointerDecay, E, nullptr,
|
||||
VK_RValue, FPOptionsOverride());
|
||||
if (E->isLValue())
|
||||
E = ImplicitCastExpr::Create(Context, E->getType().getNonReferenceType(),
|
||||
clang::CK_LValueToRValue, E, nullptr,
|
||||
VK_RValue, FPOptionsOverride());
|
||||
|
||||
Expr::EvalResult Eval;
|
||||
Notes.clear();
|
||||
Eval.Diag = &Notes;
|
||||
|
||||
bool Result =
|
||||
E->EvaluateAsConstantExpr(Eval, Context);
|
||||
|
||||
/// Result means the expression can be folded to a constant.
|
||||
/// Note.empty() means the expression is a valid constant expression in the
|
||||
/// current language mode.
|
||||
if (!Result || !Notes.empty()) {
|
||||
Diag(E->getBeginLoc(), diag::err_attribute_argument_n_type)
|
||||
<< CI << Idx << AANT_ArgumentConstantExpr;
|
||||
for (auto &Note : Notes)
|
||||
Diag(Note.first, Note.second);
|
||||
return;
|
||||
}
|
||||
assert(Eval.Val.hasValue());
|
||||
E = ConstantExpr::Create(Context, E, Eval.Val);
|
||||
}
|
||||
D->addAttr(Attr);
|
||||
}
|
||||
|
||||
static void handleAnnotateAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
|
||||
// Make sure that there is a string literal as the annotation's single
|
||||
// Make sure that there is a string literal as the annotation's first
|
||||
// argument.
|
||||
StringRef Str;
|
||||
if (!S.checkStringLiteralArgumentAttr(AL, 0, Str))
|
||||
return;
|
||||
|
||||
// Don't duplicate annotations that are already set.
|
||||
for (const auto *I : D->specific_attrs<AnnotateAttr>()) {
|
||||
if (I->getAnnotation() == Str)
|
||||
return;
|
||||
llvm::SmallVector<Expr *, 4> Args;
|
||||
Args.reserve(AL.getNumArgs());
|
||||
for (unsigned Idx = 0; Idx < AL.getNumArgs(); Idx++) {
|
||||
assert(!AL.isArgIdent(Idx));
|
||||
Args.push_back(AL.getArgAsExpr(Idx));
|
||||
}
|
||||
|
||||
D->addAttr(::new (S.Context) AnnotateAttr(S.Context, AL, Str));
|
||||
S.AddAnnotationAttr(D, AL, Str, Args);
|
||||
}
|
||||
|
||||
static void handleAlignValueAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
|
||||
|
@ -181,6 +181,22 @@ static void instantiateDependentAllocAlignAttr(
|
||||
S.AddAllocAlignAttr(New, *Align, Param);
|
||||
}
|
||||
|
||||
static void instantiateDependentAnnotationAttr(
|
||||
Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs,
|
||||
const AnnotateAttr *Attr, Decl *New) {
|
||||
EnterExpressionEvaluationContext Unevaluated(
|
||||
S, Sema::ExpressionEvaluationContext::ConstantEvaluated);
|
||||
SmallVector<Expr *, 4> Args;
|
||||
Args.reserve(Attr->args_size());
|
||||
for (auto *E : Attr->args()) {
|
||||
ExprResult Result = S.SubstExpr(E, TemplateArgs);
|
||||
if (!Result.isUsable())
|
||||
return;
|
||||
Args.push_back(Result.get());
|
||||
}
|
||||
S.AddAnnotationAttr(New, *Attr, Attr->getAnnotation(), Args);
|
||||
}
|
||||
|
||||
static Expr *instantiateDependentFunctionAttrCondition(
|
||||
Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs,
|
||||
const Attr *A, Expr *OldCond, const Decl *Tmpl, FunctionDecl *New) {
|
||||
@ -593,6 +609,10 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
|
||||
continue;
|
||||
}
|
||||
|
||||
if (const auto *Annotate = dyn_cast<AnnotateAttr>(TmplAttr)) {
|
||||
instantiateDependentAnnotationAttr(*this, TemplateArgs, Annotate, New);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (const auto *EnableIf = dyn_cast<EnableIfAttr>(TmplAttr)) {
|
||||
instantiateDependentEnableIfAttr(*this, TemplateArgs, EnableIf, Tmpl,
|
||||
|
@ -252,10 +252,12 @@ int mergeAttrTest() __attribute__((unused,no_thread_safety_analysis));
|
||||
// CHECK-NEXT: DeprecatedAttr{{.*}} Inherited
|
||||
// CHECK-NEXT: WarnUnusedResultAttr{{.*}} Inherited
|
||||
// CHECK-NEXT: AnnotateAttr{{.*}}
|
||||
// CHECK-NEXT: StringLiteral
|
||||
|
||||
// CHECK: FunctionDecl{{.*}} mergeAttrTest
|
||||
// CHECK-NEXT: DeprecatedAttr{{.*}} Inherited
|
||||
// CHECK-NEXT: WarnUnusedResultAttr{{.*}} Inherited
|
||||
// CHECK-NEXT: AnnotateAttr{{.*}} Inherited
|
||||
// CHECK-NEXT: StringLiteral
|
||||
// CHECK-NEXT: UnusedAttr
|
||||
// CHECK-NEXT: NoThreadSafetyAnalysisAttr
|
||||
|
@ -15,12 +15,12 @@ int main(int argc, char **argv) {
|
||||
f.v = argc;
|
||||
// CHECK: getelementptr inbounds %struct.foo, %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: call i8* @llvm.ptr.annotation.p0i8({{.*}}str{{.*}}str{{.*}}i32 8, i8* null)
|
||||
// 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: call i8* @llvm.ptr.annotation.p0i8({{.*}}str{{.*}}str{{.*}}i32 8, i8* null)
|
||||
// CHECK-NEXT: bitcast i8* {{.*}} to i32*
|
||||
gf.v = argc;
|
||||
// CHECK: call i8* @llvm.ptr.annotation.p0i8(i8* bitcast (%struct.foo* @gf to i8*), {{.*}}str{{.*}}str{{.*}}i32 8)
|
||||
// CHECK: call i8* @llvm.ptr.annotation.p0i8(i8* bitcast (%struct.foo* @gf to i8*), {{.*}}str{{.*}}str{{.*}}i32 8, i8* null)
|
||||
return 0;
|
||||
}
|
||||
|
@ -21,13 +21,13 @@ __attribute((address_space(1))) __attribute__((annotate("addrspace1_ann"))) char
|
||||
// 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 [11 x { i8*, i8*, i8*, i32 }] {{.*}}i8* @sfoo{{.*}}i8* @sfoo{{.*}}, section "llvm.metadata"
|
||||
// FOOS: @llvm.global.annotations = appending global [11 x { i8*, i8*, i8*, i32, i8* }] {{.*}}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 [11 x { i8*, i8*, i8*, i32 }] {{.*}}i8* @foo{{.*}}i8* @foo{{.*}}, section "llvm.metadata"
|
||||
// FOO: @llvm.global.annotations = appending global [11 x { i8*, i8*, i8*, i32, i8* }] {{.*}}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"
|
||||
@ -35,13 +35,13 @@ __attribute((address_space(1))) __attribute__((annotate("addrspace1_ann"))) char
|
||||
// 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 [11 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"
|
||||
// A: @llvm.global.annotations = appending global [11 x { i8*, i8*, i8*, i32, i8* }] {{.*}}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 [11 x { i8*, i8*, i8*, i32 }] {{.*}}i8* @a.bar{{.*}}i8* @a.bar{{.*}}, section "llvm.metadata"
|
||||
// BAR: @llvm.global.annotations = appending global [11 x { i8*, i8*, i8*, i32, i8* }] {{.*}}i8* @a.bar{{.*}}i8* @a.bar{{.*}}, section "llvm.metadata"
|
||||
|
||||
// ADDRSPACE: target triple
|
||||
// ADDRSPACE: @llvm.global.annotations = appending global {{.*}} addrspacecast (i8 addrspace(1)* @addrspace1_var to i8*), {{.*}}
|
||||
|
@ -7,4 +7,4 @@
|
||||
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 }
|
||||
// CHECK: @llvm.global.annotations = {{.*}}, i32 1, i8* null }
|
||||
|
@ -34,9 +34,9 @@ void local(void) {
|
||||
// LOCAL-LABEL: define void @local()
|
||||
// LOCAL: [[LOCALVAR:%.*]] = alloca i32,
|
||||
// LOCAL-NEXT: [[T0:%.*]] = bitcast i32* [[LOCALVAR]] to i8*
|
||||
// LOCAL-NEXT: call void @llvm.var.annotation(i8* [[T0]], i8* getelementptr inbounds ([15 x i8], [15 x i8]* @{{.*}}), i8* getelementptr inbounds ({{.*}}), i32 33)
|
||||
// LOCAL-NEXT: call void @llvm.var.annotation(i8* [[T0]], i8* getelementptr inbounds ([15 x i8], [15 x i8]* @{{.*}}), i8* getelementptr inbounds ({{.*}}), i32 33, i8* null)
|
||||
// LOCAL-NEXT: [[T0:%.*]] = bitcast i32* [[LOCALVAR]] to i8*
|
||||
// LOCAL-NEXT: call void @llvm.var.annotation(i8* [[T0]], i8* getelementptr inbounds ([15 x i8], [15 x i8]* @{{.*}}), i8* getelementptr inbounds ({{.*}}), i32 33)
|
||||
// LOCAL-NEXT: call void @llvm.var.annotation(i8* [[T0]], i8* getelementptr inbounds ([15 x i8], [15 x i8]* @{{.*}}), i8* getelementptr inbounds ({{.*}}), i32 33, i8* null)
|
||||
}
|
||||
|
||||
void local_after_return(void) {
|
||||
@ -53,5 +53,5 @@ void undef(void) {
|
||||
// UNDEF-LABEL: define void @undef()
|
||||
// UNDEF: [[UNDEFVAR:%.*]] = alloca i32,
|
||||
// UNDEF-NEXT: [[T0:%.*]] = bitcast i32* [[UNDEFVAR]] to i8*
|
||||
// UNDEF-NEXT: call void @llvm.var.annotation(i8* [[T0]], i8* getelementptr inbounds ([15 x i8], [15 x i8]* @{{.*}}), i8* getelementptr inbounds ({{.*}}), i32 52)
|
||||
// UNDEF-NEXT: call void @llvm.var.annotation(i8* [[T0]], i8* getelementptr inbounds ([15 x i8], [15 x i8]* @{{.*}}), i8* getelementptr inbounds ({{.*}}), i32 52, i8* null)
|
||||
}
|
||||
|
75
clang/test/CodeGenCXX/attr-annotate.cpp
Normal file
75
clang/test/CodeGenCXX/attr-annotate.cpp
Normal file
@ -0,0 +1,75 @@
|
||||
// RUN: %clang_cc1 %s -S -emit-llvm -triple x86_64-unknown-linux-gnu -o - | FileCheck %s
|
||||
|
||||
//CHECK: @[[STR1:.*]] = private unnamed_addr constant [{{.*}} x i8] c"{{.*}}attr-annotate.cpp\00", section "llvm.metadata"
|
||||
//CHECK: @[[STR2:.*]] = private unnamed_addr constant [4 x i8] c"abc\00", align 1
|
||||
//CHECK: @[[STR:.*]] = private unnamed_addr constant [5 x i8] c"test\00", section "llvm.metadata"
|
||||
//CHECK: @[[ARGS:.*]] = private unnamed_addr constant { i32, i8*, i32 } { i32 9, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @[[STR2:.*]], i32 0, i32 0), i32 8 }, section "llvm.metadata"
|
||||
//CHECK: @[[ARGS2:.*]] = private unnamed_addr constant { %struct.Struct } { %struct.Struct { i32* getelementptr inbounds ([2 x i32], [2 x i32]* @_ZN1AIjLj9EE2SVE, i32 0, i32 0), i32* bitcast (i8* getelementptr (i8, i8* bitcast ([2 x i32]* @_ZN1AIjLj9EE2SVE to i8*), i64 4) to i32*) } }, section "llvm.metadata"
|
||||
//CHECK: @llvm.global.annotations = appending global [2 x { i8*, i8*, i8*, i32, i8* }] [{ i8*, i8*, i8*, i32, i8* } { i8* bitcast (void (%struct.A*)* @_ZN1AIjLj9EE4testILi8EEEvv to i8*), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @[[STR:.*]], i32 0, i32 0), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* @[[STR1:.*]], i32 0, i32 0), i32 {{.*}}, i8* bitcast ({ i32, i8*, i32 }* @[[ARGS:.*]] to i8*) }, { i8*, i8*, i8*, i32, i8* } { i8* bitcast (void (%struct.A*)* @_ZN1AIjLj9EE5test2Ev to i8*), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.6, i32 0, i32 0), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* @.str.1, i32 0, i32 0), i32 24, i8* bitcast ({ %struct.Struct }* @[[ARGS2]] to i8*) }]
|
||||
|
||||
constexpr const char* str() {
|
||||
return "abc";
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
struct Struct {
|
||||
T t1;
|
||||
T t2;
|
||||
};
|
||||
|
||||
template<typename T, T V>
|
||||
struct A {
|
||||
static constexpr const T SV[] = {V, V + 1};
|
||||
template <int I> __attribute__((annotate("test", V, str(), I))) void test() {}
|
||||
__attribute__((annotate("test", Struct<const T*>{&SV[0], &SV[1]}))) void test2() {}
|
||||
};
|
||||
|
||||
void t() {
|
||||
A<unsigned, 9> a;
|
||||
a.test<8>();
|
||||
a.test2();
|
||||
}
|
||||
|
||||
template<typename T, T V>
|
||||
struct B {
|
||||
template<typename T1, T1 V1>
|
||||
struct foo {
|
||||
int v __attribute__((annotate("v_ann_0", str(), 90, V))) __attribute__((annotate("v_ann_1", V1)));
|
||||
};
|
||||
};
|
||||
|
||||
static B<int long, -1>::foo<unsigned, 9> gf;
|
||||
|
||||
// CHECK-LABEL: @main(
|
||||
// CHECK-NEXT: entry:
|
||||
// CHECK-NEXT: [[RETVAL:%.*]] = alloca i32, align 4
|
||||
// CHECK-NEXT: [[ARGC_ADDR:%.*]] = alloca i32, align 4
|
||||
// CHECK-NEXT: [[ARGV_ADDR:%.*]] = alloca i8**, align 8
|
||||
// CHECK-NEXT: [[F:%.*]] = alloca %"struct.B<int, 7>::foo", align 4
|
||||
// CHECK-NEXT: store i32 0, i32* [[RETVAL]], align 4
|
||||
// CHECK-NEXT: store i32 [[ARGC:%.*]], i32* [[ARGC_ADDR]], align 4
|
||||
// CHECK-NEXT: store i8** [[ARGV:%.*]], i8*** [[ARGV_ADDR]], align 8
|
||||
// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[ARGC_ADDR]], align 4
|
||||
// CHECK-NEXT: [[V:%.*]] = getelementptr inbounds %"struct.B<int, 7>::foo", %"struct.B<int, 7>::foo"* [[F]], i32 0, i32 0
|
||||
// CHECK-NEXT: [[TMP1:%.*]] = bitcast i32* [[V]] to i8*
|
||||
// CHECK-NEXT: [[TMP2:%.*]] = call i8* @llvm.ptr.annotation.p0i8(i8* [[TMP1]], i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str, i32 0, i32 0), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* @.str.1, i32 0, i32 0), i32 {{.*}}, i8* bitcast ({ i8*, i32, i32 }* @.args to i8*))
|
||||
// CHECK-NEXT: [[TMP3:%.*]] = bitcast i8* [[TMP2]] to i32*
|
||||
// CHECK-NEXT: [[TMP4:%.*]] = bitcast i32* [[TMP3]] to i8*
|
||||
// CHECK-NEXT: [[TMP5:%.*]] = call i8* @llvm.ptr.annotation.p0i8(i8* [[TMP4]], i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str.3, i32 0, i32 0), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* @.str.1, i32 0, i32 0), i32 {{.*}}, i8* bitcast ({ i32 }* @.args.4 to i8*))
|
||||
// CHECK-NEXT: [[TMP6:%.*]] = bitcast i8* [[TMP5]] to i32*
|
||||
// CHECK-NEXT: store i32 [[TMP0]], i32* [[TMP6]], align 4
|
||||
// CHECK-NEXT: [[TMP7:%.*]] = load i32, i32* [[ARGC_ADDR]], align 4
|
||||
// CHECK-NEXT: [[TMP8:%.*]] = call i8* @llvm.ptr.annotation.p0i8(i8* bitcast (%"struct.B<long, -1>::foo"* @_ZL2gf to i8*), i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str, i32 0, i32 0), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* @.str.1, i32 0, i32 0), i32 {{.*}}, i8* bitcast ({ i8*, i32, i64 }* @.args.5 to i8*))
|
||||
// CHECK-NEXT: [[TMP9:%.*]] = bitcast i8* [[TMP8]] to i32*
|
||||
// CHECK-NEXT: [[TMP10:%.*]] = bitcast i32* [[TMP9]] to i8*
|
||||
// CHECK-NEXT: [[TMP11:%.*]] = call i8* @llvm.ptr.annotation.p0i8(i8* [[TMP10]], i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str.3, i32 0, i32 0), i8* getelementptr inbounds ([{{.*}} x i8], [{{.*}} x i8]* @.str.1, i32 0, i32 0), i32 {{.*}}, i8* bitcast ({ i32 }* @.args.4 to i8*))
|
||||
// CHECK-NEXT: [[TMP12:%.*]] = bitcast i8* [[TMP11]] to i32*
|
||||
// CHECK-NEXT: store i32 [[TMP7]], i32* [[TMP12]], align 4
|
||||
// CHECK-NEXT: ret i32 0
|
||||
//
|
||||
int main(int argc, char **argv) {
|
||||
B<int, 7>::foo<unsigned, 9> f;
|
||||
f.v = argc;
|
||||
gf.v = argc;
|
||||
return 0;
|
||||
}
|
22
clang/test/CodeGenCXX/attr-annotate2.cpp
Normal file
22
clang/test/CodeGenCXX/attr-annotate2.cpp
Normal file
@ -0,0 +1,22 @@
|
||||
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
|
||||
// RUN: %clang_cc1 %s -S -emit-llvm -triple x86_64-unknown-linux-gnu -o - | FileCheck %s
|
||||
|
||||
// CHECK: @[[STR:.*]] = private unnamed_addr constant [45 x i8] c"_Generic selection expression should be fine\00", section "llvm.metadata"
|
||||
// CHECK-NEXT: @[[FILENAME:.*]] = private unnamed_addr constant {{.*}}, section "llvm.metadata"
|
||||
// CHECK-NEXT: @[[ARGS:.*]] = private unnamed_addr constant { i32 } zeroinitializer, section "llvm.metadata"
|
||||
|
||||
// CHECK-LABEL: @_Z1fv(
|
||||
// CHECK-NEXT: entry:
|
||||
// CHECK-NEXT: [[N:%.*]] = alloca i32, align 4
|
||||
// CHECK-NEXT: [[J:%.*]] = alloca i32, align 4
|
||||
// CHECK-NEXT: store i32 10, i32* [[N]], align 4
|
||||
// CHECK-NEXT: [[J1:%.*]] = bitcast i32* [[J]] to i8*
|
||||
// CHECK-NEXT: call void @llvm.var.annotation(i8* [[J1]], i8* getelementptr inbounds ([45 x i8], [45 x i8]* @[[STR]], i32 0, i32 0), i8* getelementptr inbounds ([{{[0-9]+}} x i8], [{{[0-9]+}} x i8]* @[[FILENAME]], i32 0, i32 0), i32 {{.*}}, i8* bitcast ({ i32 }* @[[ARGS]] to i8*))
|
||||
// CHECK-NEXT: store i32 0, i32* [[J]], align 4
|
||||
// CHECK-NEXT: ret void
|
||||
//
|
||||
void f() {
|
||||
int n = 10;
|
||||
[[clang::annotate("_Generic selection expression should be fine", _Generic(n, int : 0, default : 1))]]
|
||||
int j = 0; // second arg should resolve to 0 fine
|
||||
}
|
@ -21,11 +21,15 @@ class testClass2 {
|
||||
// CHECK: CXXMethodDecl{{.*}} testMethod1
|
||||
// CHECK-NEXT: ParmVarDecl{{.*}} param
|
||||
// CHECK-NEXT: AnnotateAttr{{.*}} "test"
|
||||
// CHECK-NEXT: StringLiteral
|
||||
// CHECK-NEXT: AnnotateAttr{{.*}} "test"
|
||||
// CHECK-NEXT: StringLiteral
|
||||
// CHECK-NEXT: CXXConstructorDecl
|
||||
// CHECK-NEXT: AnnotateAttr{{.*}} "test"
|
||||
// CHECK-NEXT: StringLiteral
|
||||
// CHECK-NEXT: CXXMethodDecl{{.*}} operator->
|
||||
// CHECK-NEXT: AnnotateAttr{{.*}} "test"
|
||||
// CHECK-NEXT: StringLiteral
|
||||
|
||||
#pragma clang attribute push (__attribute__((annotate("method"))), apply_to=any(record, field, variable, function, namespace, type_alias))
|
||||
|
||||
@ -36,19 +40,25 @@ void testClass2::testMethod1(int param) {
|
||||
// CHECK-LABEL: CXXMethodDecl{{.*}}prev{{.*}} testMethod1
|
||||
// CHECK-NEXT: ParmVarDecl{{.*}} param
|
||||
// CHECK-NEXT: AnnotateAttr{{.*}} "test"
|
||||
// CHECK-NEXT: StringLiteral
|
||||
// CHECK-NEXT: AnnotateAttr{{.*}} "method"
|
||||
// CHECK-NEXT: StringLiteral
|
||||
// CHECK-NEXT: CompoundStmt
|
||||
// CHECK-NEXT: AnnotateAttr{{.*}} "test"
|
||||
// CHECK-NEXT: StringLiteral
|
||||
// CHECK-NEXT: AnnotateAttr{{.*}} "method"
|
||||
// CHECK-NEXT: StringLiteral
|
||||
|
||||
namespace testNamespace {
|
||||
}
|
||||
// CHECK-LABEL: NamespaceDecl{{.*}} testNamespace
|
||||
// CHECK-NEXT: AnnotateAttr{{.*}} "test"
|
||||
// CHECK-NEXT: StringLiteral
|
||||
|
||||
class testClassForward;
|
||||
// CHECK-LABEL: CXXRecordDecl{{.*}} testClassForward
|
||||
// CHECK-NEXT: AnnotateAttr{{.*}} "test"
|
||||
// CHECK-NEXT: StringLiteral
|
||||
|
||||
namespace testNamespaceAlias = testNamespace;
|
||||
// CHECK-LABEL: NamespaceAliasDecl{{.*}} testNamespaceAlias
|
||||
@ -68,6 +78,7 @@ void testCatchVariable() {
|
||||
// CHECK: CXXCatchStmt
|
||||
// CHECK-NEXT: VarDecl{{.*}} testCatch
|
||||
// CHECK-NEXT: AnnotateAttr{{.*}} "test"
|
||||
// CHECK-NEXT: StringLiteral
|
||||
|
||||
void testLambdaMethod() {
|
||||
auto l = [] () { };
|
||||
@ -79,6 +90,7 @@ void testLambdaMethod() {
|
||||
// CHECK: CXXMethodDecl{{.*}} operator()
|
||||
// CHECK-NEXT: CompoundStmt
|
||||
// CHECK-NEXT: AnnotateAttr{{.*}} "test"
|
||||
// CHECK-NEXT: StringLiteral
|
||||
|
||||
#pragma clang attribute pop
|
||||
|
||||
|
@ -8,6 +8,7 @@
|
||||
// CHECK-LABEL: ObjCInterfaceDecl{{.*}}testInterface1
|
||||
// CHECK-NEXT: ObjCImplementation
|
||||
// CHECK-NEXT: AnnotateAttr{{.*}} "test"
|
||||
// CHECK-NEXT: StringLiteral
|
||||
// CHECK-NEXT: ObjCSubclassingRestrictedAttr{{.*}}
|
||||
|
||||
// CHECK-NOT: AnnotateAttr
|
||||
@ -17,24 +18,29 @@
|
||||
int testIvar1;
|
||||
// CHECK-LABEL: ObjCIvarDecl{{.*}} testIvar1
|
||||
// CHECK-NEXT: AnnotateAttr{{.*}} "test"
|
||||
// CHECK-NEXT: StringLiteral
|
||||
// CHECK-NOT: ObjCSubclassingRestrictedAttr
|
||||
}
|
||||
|
||||
@property int testProp1;
|
||||
// CHECK-LABEL: ObjCPropertyDecl{{.*}} testProp1
|
||||
// CHECK-NEXT: AnnotateAttr{{.*}} "test"
|
||||
// CHECK-NEXT: StringLiteral
|
||||
// CHECK-NOT: ObjCSubclassingRestrictedAttr
|
||||
|
||||
- (void)testIm:(int) x;
|
||||
// CHECK-LABEL: ObjCMethodDecl{{.*}}testIm
|
||||
// CHECK-NEXT: ParmVarDecl{{.*}} x
|
||||
// CHECK-NEXT: AnnotateAttr{{.*}} "test"
|
||||
// CHECK-NEXT: StringLiteral
|
||||
// CHECK-NEXT: AnnotateAttr{{.*}} "test"
|
||||
// CHECK-NEXT: StringLiteral
|
||||
// CHECK-NOT: ObjCSubclassingRestrictedAttr
|
||||
|
||||
+ (void)testCm;
|
||||
// CHECK-LABEL: ObjCMethodDecl{{.*}}testCm
|
||||
// CHECK-NEXT: AnnotateAttr{{.*}} "test"
|
||||
// CHECK-NEXT: StringLiteral
|
||||
// CHECK-NOT: ObjCSubclassingRestrictedAttr
|
||||
|
||||
// Implicit getters/setters shouldn't receive the attributes.
|
||||
@ -56,6 +62,7 @@
|
||||
int testIvar2;
|
||||
// CHECK-LABEL: ObjCIvarDecl{{.*}} testIvar2
|
||||
// CHECK-NEXT: AnnotateAttr{{.*}} "test"
|
||||
// CHECK-NEXT: StringLiteral
|
||||
// CHECK-NOT: ObjCSubclassingRestrictedAttr
|
||||
}
|
||||
|
||||
@ -66,8 +73,10 @@
|
||||
// CHECK-NEXT: ImplicitParamDecl
|
||||
// CHECK-NEXT: ParmVarDecl{{.*}} x
|
||||
// CHECK-NEXT: AnnotateAttr{{.*}} "test"
|
||||
// CHECK-NEXT: StringLiteral
|
||||
// CHECK-NEXT: CompoundStmt
|
||||
// CHECK-NEXT: AnnotateAttr{{.*}} "test"
|
||||
// CHECK-NEXT: StringLiteral
|
||||
// CHECK-NOT: ObjCSubclassingRestrictedAttr
|
||||
}
|
||||
|
||||
@ -89,8 +98,10 @@
|
||||
// CHECK-LABEL: ObjCInterfaceDecl{{.*}}testImplWithoutInterface
|
||||
// CHECK-NEXT: ObjCImplementation
|
||||
// CHECK-NEXT: AnnotateAttr{{.*}} "test"
|
||||
// CHECK-NEXT: StringLiteral
|
||||
// CHECK-NEXT: ObjCSubclassingRestrictedAttr
|
||||
// CHECK-NEXT: AnnotateAttr{{.*}} "applied at container start"
|
||||
// CHECK-NEXT: StringLiteral
|
||||
|
||||
// CHECK-LABEL: ObjCImplementationDecl{{.*}}testImplWithoutInterface
|
||||
// CHECK-NOT: AnnotateAttr
|
||||
@ -103,12 +114,14 @@
|
||||
@protocol testProtocol
|
||||
// CHECK-LABEL: ObjCProtocolDecl{{.*}}testProtocol
|
||||
// CHECK-NEXT: AnnotateAttr{{.*}} "test"
|
||||
// CHECK-NEXT: StringLiteral
|
||||
// CHECK-NOT: ObjCSubclassingRestrictedAttr
|
||||
// CHECK-NOT: AnnotateAttr
|
||||
|
||||
- (void)testProtIm;
|
||||
// CHECK-LABEL: ObjCMethodDecl{{.*}}testProtIm
|
||||
// CHECK-NEXT: AnnotateAttr{{.*}} "test"
|
||||
// CHECK-NEXT: StringLiteral
|
||||
// CHECK-NOT: ObjCSubclassingRestrictedAttr
|
||||
|
||||
@end
|
||||
@ -116,6 +129,7 @@
|
||||
@protocol testForwardProtocol;
|
||||
// CHECK-LABEL: ObjCProtocolDecl{{.*}}testForwardProtocol
|
||||
// CHECK-NEXT: AnnotateAttr{{.*}} "test"
|
||||
// CHECK-NEXT: StringLiteral
|
||||
// CHECK-NOT: ObjCSubclassingRestrictedAttr
|
||||
|
||||
|
||||
@ -152,6 +166,7 @@
|
||||
@interface testInterface3
|
||||
// CHECK-LABEL: ObjCInterfaceDecl{{.*}}testInterface3
|
||||
// CHECK-NEXT: AnnotateAttr{{.*}} "test"
|
||||
// CHECK-NEXT: StringLiteral
|
||||
// CHECK-NOT: ObjCSubclassingRestrictedAttr
|
||||
@end
|
||||
|
||||
|
@ -5,7 +5,7 @@ public __attribute__((unavailable)): // expected-error {{access specifier can on
|
||||
void foo();
|
||||
private __attribute__((annotate("foobar"))):
|
||||
void bar();
|
||||
private __attribute__((annotate())): // expected-error {{'annotate' attribute takes one argument}}
|
||||
private __attribute__((annotate())): // expected-error {{'annotate' attribute takes at least 1 argument}}
|
||||
};
|
||||
|
||||
void f(X x) {
|
||||
|
@ -41,7 +41,7 @@ typedef int AVAIL_ATTR unavail_int; // expected-note {{marked as being introduce
|
||||
|
||||
I5 *i5;
|
||||
|
||||
// expected-error@+1 2 {{'annotate' attribute takes one argument}}
|
||||
// expected-error@+1 2 {{'annotate' attribute takes at least 1 argument}}
|
||||
#pragma clang attribute push (__attribute__((annotate)), apply_to=objc_implementation)
|
||||
@interface I6 @end
|
||||
@interface I6 (MyCat) @end
|
||||
|
@ -5,8 +5,8 @@ void __attribute__((annotate("foo"))) foo(float *a) {
|
||||
[[clang::annotate("bar")]] int x2;
|
||||
__attribute__((annotate(1))) int y; // expected-error {{'annotate' attribute requires a string}}
|
||||
[[clang::annotate(1)]] int y2; // expected-error {{'annotate' attribute requires a string}}
|
||||
__attribute__((annotate("bar", 1))) int z; // expected-error {{'annotate' attribute takes one argument}}
|
||||
[[clang::annotate("bar", 1)]] int z2; // expected-error {{'annotate' attribute takes one argument}}
|
||||
__attribute__((annotate("bar", 1))) int z;
|
||||
[[clang::annotate("bar", 1)]] int z2;
|
||||
|
||||
int u = __builtin_annotation(z, (char*) 0); // expected-error {{second argument to __builtin_annotation must be a non-wide string constant}}
|
||||
int v = __builtin_annotation(z, (char*) L"bar"); // expected-error {{second argument to __builtin_annotation must be a non-wide string constant}}
|
||||
|
@ -7,18 +7,18 @@
|
||||
#pragma clang attribute pop // expected-note {{'#pragma clang attribute push' regions ends here}}
|
||||
|
||||
// Ensure we only report any errors once.
|
||||
#pragma clang attribute push (__attribute__((annotate)), apply_to = function) // expected-error 4 {{'annotate' attribute takes one argument}}
|
||||
#pragma clang attribute push (__attribute__((annotate)), apply_to = function) // expected-error 4 {{'annotate' attribute takes at least 1 argument}}
|
||||
|
||||
void test5_begin(); // expected-note {{when applied to this declaration}}
|
||||
void test5_1(); // expected-note {{when applied to this declaration}}
|
||||
|
||||
#pragma clang attribute push (__attribute__((annotate())), apply_to = function) // expected-error 2 {{'annotate' attribute takes one argument}}
|
||||
#pragma clang attribute push (__attribute__((annotate())), apply_to = function) // expected-error 2 {{'annotate' attribute takes at least 1 argument}}
|
||||
|
||||
void test5_2(); // expected-note 2 {{when applied to this declaration}}
|
||||
|
||||
#pragma clang attribute push (__attribute__((annotate("hello", "world"))), apply_to = function) // expected-error {{'annotate' attribute takes one argument}}
|
||||
#pragma clang attribute push (__attribute__((annotate("hello", "world"))), apply_to = function)
|
||||
|
||||
void test5_3(); // expected-note 3 {{when applied to this declaration}}
|
||||
void test5_3(); // expected-note 2 {{when applied to this declaration}}
|
||||
|
||||
#pragma clang attribute pop
|
||||
#pragma clang attribute pop
|
||||
@ -38,8 +38,8 @@ __attribute__((always_inline)) void optnone3() { } // expected-warning {{'always
|
||||
|
||||
#pragma clang attribute pop
|
||||
|
||||
#pragma clang attribute push (__attribute__((annotate())), apply_to = function) // expected-error{{'annotate' attribute takes one argument}}
|
||||
#pragma clang attribute (__attribute__((annotate())), apply_to = function) // expected-error{{'annotate' attribute takes one argument}}
|
||||
#pragma clang attribute push (__attribute__((annotate())), apply_to = function) // expected-error{{'annotate' attribute takes at least 1 argument}}
|
||||
#pragma clang attribute (__attribute__((annotate())), apply_to = function) // expected-error{{'annotate' attribute takes at least 1 argument}}
|
||||
|
||||
void fun(); // expected-note 2 {{when applied to this declaration}}
|
||||
|
||||
@ -48,11 +48,11 @@ void fun(); // expected-note 2 {{when applied to this declaration}}
|
||||
|
||||
|
||||
#pragma clang attribute push
|
||||
#pragma clang attribute (__attribute__((annotate())), apply_to = function) // expected-error 2 {{'annotate' attribute takes one argument}}
|
||||
#pragma clang attribute (__attribute__((annotate())), apply_to = function) // expected-error 2 {{'annotate' attribute takes at least 1 argument}}
|
||||
|
||||
void fun2(); // expected-note {{when applied to this declaration}}
|
||||
|
||||
#pragma clang attribute push (__attribute__((annotate())), apply_to = function) // expected-error{{'annotate' attribute takes one argument}}
|
||||
#pragma clang attribute push (__attribute__((annotate())), apply_to = function) // expected-error{{'annotate' attribute takes at least 1 argument}}
|
||||
void fun3(); // expected-note 2 {{when applied to this declaration}}
|
||||
#pragma clang attribute pop
|
||||
|
||||
|
130
clang/test/SemaCXX/attr-annotate.cpp
Normal file
130
clang/test/SemaCXX/attr-annotate.cpp
Normal file
@ -0,0 +1,130 @@
|
||||
// RUN: %clang_cc1 -std=gnu++20 -fsyntax-only -verify %s
|
||||
|
||||
template<bool If, typename Type>
|
||||
struct enable_if {
|
||||
using type= Type;
|
||||
};
|
||||
|
||||
template<typename Type>
|
||||
struct enable_if<false, Type> {};
|
||||
|
||||
template<typename T1, typename T2>
|
||||
struct is_same {
|
||||
static constexpr bool value = false;
|
||||
};
|
||||
|
||||
template<typename T1>
|
||||
struct is_same<T1, T1> {
|
||||
static constexpr bool value = true;
|
||||
};
|
||||
|
||||
constexpr const char *str() {
|
||||
return "abc";
|
||||
}
|
||||
|
||||
template<typename T, typename enable_if<!is_same<int, T>::value, int>::type = 0>
|
||||
constexpr T fail_on_int(T t) {return t;}
|
||||
// expected-note@-1 {{candidate template ignored: requirement}}
|
||||
|
||||
namespace test0 {
|
||||
template<typename T, T v>
|
||||
struct A {
|
||||
[[clang::annotate("test", fail_on_int(v))]] void t() {}
|
||||
// expected-error@-1 {{no matching function for call to 'fail_on_int'}}
|
||||
[[clang::annotate("test", (typename enable_if<!is_same<long, T>::value, int>::type)v)]] void t1() {}
|
||||
// expected-error@-1 {{failed requirement}}
|
||||
};
|
||||
A<int, 9> a;
|
||||
// expected-note@-1 {{in instantiation of template class}}
|
||||
A<long, 7> a1;
|
||||
// expected-note@-1 {{in instantiation of template class}}
|
||||
A<unsigned long, 6> a2;
|
||||
|
||||
template<typename T>
|
||||
struct B {
|
||||
[[clang::annotate("test", (T{}, 9))]] void t() {}
|
||||
// expected-error@-1 {{illegal initializer type 'void'}}
|
||||
};
|
||||
B<int> b;
|
||||
B<void> b1;
|
||||
// expected-note@-1 {{in instantiation of template class}}
|
||||
}
|
||||
|
||||
namespace test1 {
|
||||
int g_i; // expected-note {{declared here}}
|
||||
|
||||
[[clang::annotate("test", "arg")]] void t3() {}
|
||||
|
||||
template <typename T, T V>
|
||||
struct B {
|
||||
static T b; // expected-note {{declared here}}
|
||||
static constexpr T cb = V;
|
||||
template <typename T1, T1 V1>
|
||||
struct foo {
|
||||
static T1 f; // expected-note {{declared here}}
|
||||
static constexpr T1 cf = V1;
|
||||
int v __attribute__((annotate("v_ann_0", str(), 90, V, g_i))) __attribute__((annotate("v_ann_1", V1)));
|
||||
// expected-error@-1 {{'annotate' attribute requires parameter 4 to be a constant expression}}
|
||||
// expected-note@-2 {{is not allowed in a constant expression}}
|
||||
[[clang::annotate("qdwqwd", cf, cb)]] void t() {}
|
||||
[[clang::annotate("qdwqwd", f, cb)]] void t1() {}
|
||||
// expected-error@-1 {{'annotate' attribute requires parameter 1 to be a constant expression}}
|
||||
// expected-note@-2 {{is not allowed in a constant expression}}
|
||||
[[clang::annotate("jui", b, cf)]] void t2() {}
|
||||
// expected-error@-1 {{'annotate' attribute requires parameter 1 to be a constant expression}}
|
||||
// expected-note@-2 {{is not allowed in a constant expression}}
|
||||
[[clang::annotate("jui", (b, 0), cf)]] [[clang::annotate("jui", &b, cf, &foo::t2, str())]] void t3() {}
|
||||
};
|
||||
};
|
||||
|
||||
static B<int long, -1>::foo<unsigned, 9> gf; // expected-note {{in instantiation of}}
|
||||
static B<int long, -2> gf1;
|
||||
|
||||
} // namespace test1
|
||||
|
||||
namespace test2 {
|
||||
|
||||
template<int I>
|
||||
int f() {
|
||||
[[clang::annotate("test", I)]] int v = 0; // expected-note {{declared here}}
|
||||
[[clang::annotate("test", v)]] int v2 = 0;
|
||||
// expected-error@-1 {{'annotate' attribute requires parameter 1 to be a constant expression}}
|
||||
// expected-note@-2 {{is not allowed in a constant expression}}
|
||||
[[clang::annotate("test", rtyui)]] int v3 = 0;
|
||||
// expected-error@-1 {{use of undeclared identifier 'rtyui'}}
|
||||
}
|
||||
|
||||
void test() {}
|
||||
}
|
||||
|
||||
namespace test3 {
|
||||
|
||||
void f() {
|
||||
int n = 10;
|
||||
int vla[n];
|
||||
|
||||
[[clang::annotate("vlas are awful", sizeof(vla))]] int i = 0; // reject, the sizeof is not unevaluated
|
||||
// expected-error@-1 {{'annotate' attribute requires parameter 1 to be a constant expression}}
|
||||
// expected-note@-2 {{subexpression not valid in a constant expression}}
|
||||
[[clang::annotate("_Generic selection expression should be fine", _Generic(n, int : 0, default : 1))]]
|
||||
int j = 0; // second arg should resolve to 0 fine
|
||||
}
|
||||
void designator();
|
||||
[[clang::annotate("function designators?", designator)]] int k = 0; // Should work?
|
||||
|
||||
void self() {
|
||||
[[clang::annotate("function designators?", self)]] int k = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace test4 {
|
||||
constexpr int foldable_but_invalid() {
|
||||
int *A = new int(0);
|
||||
// expected-note@-1 {{allocation performed here was not deallocated}}
|
||||
return *A;
|
||||
}
|
||||
|
||||
[[clang::annotate("", foldable_but_invalid())]] void f1() {}
|
||||
// expected-error@-1 {{'annotate' attribute requires parameter 1 to be a constant expression}}
|
||||
}
|
@ -953,11 +953,11 @@ def int_eh_sjlj_setup_dispatch : Intrinsic<[], []>;
|
||||
//
|
||||
def int_var_annotation : DefaultAttrsIntrinsic<[],
|
||||
[llvm_ptr_ty, llvm_ptr_ty,
|
||||
llvm_ptr_ty, llvm_i32_ty],
|
||||
llvm_ptr_ty, llvm_i32_ty, llvm_ptr_ty],
|
||||
[IntrWillReturn], "llvm.var.annotation">;
|
||||
def int_ptr_annotation : DefaultAttrsIntrinsic<[LLVMAnyPointerType<llvm_anyint_ty>],
|
||||
[LLVMMatchType<0>, llvm_ptr_ty, llvm_ptr_ty,
|
||||
llvm_i32_ty],
|
||||
llvm_i32_ty, llvm_ptr_ty],
|
||||
[IntrWillReturn], "llvm.ptr.annotation">;
|
||||
def int_annotation : DefaultAttrsIntrinsic<[llvm_anyint_ty],
|
||||
[LLVMMatchType<0>, llvm_ptr_ty,
|
||||
|
@ -15,8 +15,8 @@ define i32 @trivially_free() {
|
||||
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.lifetime.start.p0i8(i64 1, i8* undef)
|
||||
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.lifetime.end.p0i8(i64 1, i8* undef)
|
||||
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a5 = call i64 @llvm.objectsize.i64.p0i8(i8* undef, i1 true, i1 true, i1 true)
|
||||
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a6 = call i8* @llvm.ptr.annotation.p0i8(i8* undef, i8* undef, i8* undef, i32 undef)
|
||||
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.var.annotation(i8* undef, i8* undef, i8* undef, i32 undef)
|
||||
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a6 = call i8* @llvm.ptr.annotation.p0i8(i8* undef, i8* undef, i8* undef, i32 undef, i8* undef)
|
||||
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.var.annotation(i8* undef, i8* undef, i8* undef, i32 undef, i8* undef)
|
||||
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 undef
|
||||
;
|
||||
; CHECK-THROUGHPUT-LABEL: 'trivially_free'
|
||||
@ -31,8 +31,8 @@ define i32 @trivially_free() {
|
||||
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.lifetime.start.p0i8(i64 1, i8* undef)
|
||||
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.lifetime.end.p0i8(i64 1, i8* undef)
|
||||
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a5 = call i64 @llvm.objectsize.i64.p0i8(i8* undef, i1 true, i1 true, i1 true)
|
||||
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a6 = call i8* @llvm.ptr.annotation.p0i8(i8* undef, i8* undef, i8* undef, i32 undef)
|
||||
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.var.annotation(i8* undef, i8* undef, i8* undef, i32 undef)
|
||||
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a6 = call i8* @llvm.ptr.annotation.p0i8(i8* undef, i8* undef, i8* undef, i32 undef, i8* undef)
|
||||
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.var.annotation(i8* undef, i8* undef, i8* undef, i32 undef, i8* undef)
|
||||
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 undef
|
||||
;
|
||||
%a0 = call i32 @llvm.annotation.i32(i32 undef, i8* undef, i8* undef, i32 undef)
|
||||
@ -49,8 +49,8 @@ define i32 @trivially_free() {
|
||||
call void @llvm.lifetime.start.p0i8(i64 1, i8* undef)
|
||||
call void @llvm.lifetime.end.p0i8(i64 1, i8* undef)
|
||||
%a5 = call i64 @llvm.objectsize.i64.p0i8(i8* undef, i1 1, i1 1, i1 1)
|
||||
%a6 = call i8* @llvm.ptr.annotation.p0i8(i8* undef, i8* undef, i8* undef, i32 undef)
|
||||
call void @llvm.var.annotation(i8* undef, i8* undef, i8* undef, i32 undef)
|
||||
%a6 = call i8* @llvm.ptr.annotation.p0i8(i8* undef, i8* undef, i8* undef, i32 undef, i8* undef)
|
||||
call void @llvm.var.annotation(i8* undef, i8* undef, i8* undef, i32 undef, i8* undef)
|
||||
ret i32 undef
|
||||
}
|
||||
|
||||
@ -68,8 +68,8 @@ declare i1 @llvm.is.constant.i32(i32)
|
||||
declare void @llvm.lifetime.start.p0i8(i64, i8*)
|
||||
declare void @llvm.lifetime.end.p0i8(i64, i8*)
|
||||
declare i64 @llvm.objectsize.i64.p0i8(i8*, i1, i1, i1)
|
||||
declare i8* @llvm.ptr.annotation.p0i8(i8*, i8*, i8*, i32)
|
||||
declare void @llvm.var.annotation(i8*, i8*, i8*, i32)
|
||||
declare i8* @llvm.ptr.annotation.p0i8(i8*, i8*, i8*, i32, i8*)
|
||||
declare void @llvm.var.annotation(i8*, i8*, i8*, i32, i8*)
|
||||
|
||||
|
||||
!0 = !DILocalVariable(scope: !1)
|
||||
|
@ -17,8 +17,8 @@ define i32 @trivially_free() {
|
||||
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.lifetime.start.p0i8(i64 1, i8* undef)
|
||||
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.lifetime.end.p0i8(i64 1, i8* undef)
|
||||
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a5 = call i64 @llvm.objectsize.i64.p0i8(i8* undef, i1 true, i1 true, i1 true)
|
||||
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a6 = call i8* @llvm.ptr.annotation.p0i8(i8* undef, i8* undef, i8* undef, i32 undef)
|
||||
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.var.annotation(i8* undef, i8* undef, i8* undef, i32 undef)
|
||||
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a6 = call i8* @llvm.ptr.annotation.p0i8(i8* undef, i8* undef, i8* undef, i32 undef, i8* undef)
|
||||
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.var.annotation(i8* undef, i8* undef, i8* undef, i32 undef, i8* undef)
|
||||
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 undef
|
||||
;
|
||||
; CHECK-THROUGHPUT-LABEL: 'trivially_free'
|
||||
@ -33,8 +33,8 @@ define i32 @trivially_free() {
|
||||
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.lifetime.start.p0i8(i64 1, i8* undef)
|
||||
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.lifetime.end.p0i8(i64 1, i8* undef)
|
||||
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a5 = call i64 @llvm.objectsize.i64.p0i8(i8* undef, i1 true, i1 true, i1 true)
|
||||
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a6 = call i8* @llvm.ptr.annotation.p0i8(i8* undef, i8* undef, i8* undef, i32 undef)
|
||||
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.var.annotation(i8* undef, i8* undef, i8* undef, i32 undef)
|
||||
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a6 = call i8* @llvm.ptr.annotation.p0i8(i8* undef, i8* undef, i8* undef, i32 undef, i8* undef)
|
||||
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.var.annotation(i8* undef, i8* undef, i8* undef, i32 undef, i8* undef)
|
||||
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 undef
|
||||
;
|
||||
%a0 = call i32 @llvm.annotation.i32(i32 undef, i8* undef, i8* undef, i32 undef)
|
||||
@ -51,8 +51,8 @@ define i32 @trivially_free() {
|
||||
call void @llvm.lifetime.start.p0i8(i64 1, i8* undef)
|
||||
call void @llvm.lifetime.end.p0i8(i64 1, i8* undef)
|
||||
%a5 = call i64 @llvm.objectsize.i64.p0i8(i8* undef, i1 1, i1 1, i1 1)
|
||||
%a6 = call i8* @llvm.ptr.annotation.p0i8(i8* undef, i8* undef, i8* undef, i32 undef)
|
||||
call void @llvm.var.annotation(i8* undef, i8* undef, i8* undef, i32 undef)
|
||||
%a6 = call i8* @llvm.ptr.annotation.p0i8(i8* undef, i8* undef, i8* undef, i32 undef, i8* undef)
|
||||
call void @llvm.var.annotation(i8* undef, i8* undef, i8* undef, i32 undef, i8* undef)
|
||||
ret i32 undef
|
||||
}
|
||||
|
||||
@ -70,8 +70,8 @@ declare i1 @llvm.is.constant.i32(i32)
|
||||
declare void @llvm.lifetime.start.p0i8(i64, i8*)
|
||||
declare void @llvm.lifetime.end.p0i8(i64, i8*)
|
||||
declare i64 @llvm.objectsize.i64.p0i8(i8*, i1, i1, i1)
|
||||
declare i8* @llvm.ptr.annotation.p0i8(i8*, i8*, i8*, i32)
|
||||
declare void @llvm.var.annotation(i8*, i8*, i8*, i32)
|
||||
declare i8* @llvm.ptr.annotation.p0i8(i8*, i8*, i8*, i32, i8*)
|
||||
declare void @llvm.var.annotation(i8*, i8*, i8*, i32, i8*)
|
||||
|
||||
|
||||
!0 = !DILocalVariable(scope: !1)
|
||||
|
@ -15,8 +15,8 @@ define i32 @trivially_free() {
|
||||
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.lifetime.start.p0i8(i64 1, i8* undef)
|
||||
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.lifetime.end.p0i8(i64 1, i8* undef)
|
||||
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a5 = call i64 @llvm.objectsize.i64.p0i8(i8* undef, i1 true, i1 true, i1 true)
|
||||
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a6 = call i8* @llvm.ptr.annotation.p0i8(i8* undef, i8* undef, i8* undef, i32 undef)
|
||||
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.var.annotation(i8* undef, i8* undef, i8* undef, i32 undef)
|
||||
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a6 = call i8* @llvm.ptr.annotation.p0i8(i8* undef, i8* undef, i8* undef, i32 undef, i8* undef)
|
||||
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.var.annotation(i8* undef, i8* undef, i8* undef, i32 undef, i8* undef)
|
||||
; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 undef
|
||||
;
|
||||
; CHECK-THROUGHPUT-LABEL: 'trivially_free'
|
||||
@ -31,8 +31,8 @@ define i32 @trivially_free() {
|
||||
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.lifetime.start.p0i8(i64 1, i8* undef)
|
||||
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.lifetime.end.p0i8(i64 1, i8* undef)
|
||||
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a5 = call i64 @llvm.objectsize.i64.p0i8(i8* undef, i1 true, i1 true, i1 true)
|
||||
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a6 = call i8* @llvm.ptr.annotation.p0i8(i8* undef, i8* undef, i8* undef, i32 undef)
|
||||
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.var.annotation(i8* undef, i8* undef, i8* undef, i32 undef)
|
||||
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a6 = call i8* @llvm.ptr.annotation.p0i8(i8* undef, i8* undef, i8* undef, i32 undef, i8* undef)
|
||||
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.var.annotation(i8* undef, i8* undef, i8* undef, i32 undef, i8* undef)
|
||||
; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 undef
|
||||
;
|
||||
%a0 = call i32 @llvm.annotation.i32(i32 undef, i8* undef, i8* undef, i32 undef)
|
||||
@ -49,8 +49,8 @@ define i32 @trivially_free() {
|
||||
call void @llvm.lifetime.start.p0i8(i64 1, i8* undef)
|
||||
call void @llvm.lifetime.end.p0i8(i64 1, i8* undef)
|
||||
%a5 = call i64 @llvm.objectsize.i64.p0i8(i8* undef, i1 1, i1 1, i1 1)
|
||||
%a6 = call i8* @llvm.ptr.annotation.p0i8(i8* undef, i8* undef, i8* undef, i32 undef)
|
||||
call void @llvm.var.annotation(i8* undef, i8* undef, i8* undef, i32 undef)
|
||||
%a6 = call i8* @llvm.ptr.annotation.p0i8(i8* undef, i8* undef, i8* undef, i32 undef, i8* undef)
|
||||
call void @llvm.var.annotation(i8* undef, i8* undef, i8* undef, i32 undef, i8* undef)
|
||||
ret i32 undef
|
||||
}
|
||||
|
||||
@ -68,8 +68,8 @@ declare i1 @llvm.is.constant.i32(i32)
|
||||
declare void @llvm.lifetime.start.p0i8(i64, i8*)
|
||||
declare void @llvm.lifetime.end.p0i8(i64, i8*)
|
||||
declare i64 @llvm.objectsize.i64.p0i8(i8*, i1, i1, i1)
|
||||
declare i8* @llvm.ptr.annotation.p0i8(i8*, i8*, i8*, i32)
|
||||
declare void @llvm.var.annotation(i8*, i8*, i8*, i32)
|
||||
declare i8* @llvm.ptr.annotation.p0i8(i8*, i8*, i8*, i32, i8*)
|
||||
declare void @llvm.var.annotation(i8*, i8*, i8*, i32, i8*)
|
||||
|
||||
|
||||
!0 = !DILocalVariable(scope: !1)
|
||||
|
@ -10,9 +10,9 @@
|
||||
define void @foo() {
|
||||
entry:
|
||||
%m = alloca i8, align 4
|
||||
%0 = call i8* @llvm.ptr.annotation.p0i8(i8* %m, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str1, i32 0, i32 0), i32 2)
|
||||
%0 = call i8* @llvm.ptr.annotation.p0i8(i8* %m, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str1, i32 0, i32 0), i32 2, i8* null)
|
||||
store i8 1, i8* %0, align 4
|
||||
ret void
|
||||
}
|
||||
|
||||
declare i8* @llvm.ptr.annotation.p0i8(i8*, i8*, i8*, i32) #1
|
||||
declare i8* @llvm.ptr.annotation.p0i8(i8*, i8*, i8*, i32, i8*) #1
|
||||
|
@ -15,7 +15,7 @@ define i32 @assume_inevitable(i32* %a, i32* %b, i8* %c) {
|
||||
; CHECK-NEXT: [[DUMMY_EQ:%.*]] = icmp ugt i32 [[LOADRES]], 42
|
||||
; CHECK-NEXT: tail call void @llvm.assume(i1 [[DUMMY_EQ]])
|
||||
; CHECK-NEXT: [[M_I8:%.*]] = bitcast i64* [[M]] to i8*
|
||||
; CHECK-NEXT: [[M_A:%.*]] = call i8* @llvm.ptr.annotation.p0i8(i8* nonnull [[M_I8]], i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str1, i64 0, i64 0), i32 2)
|
||||
; CHECK-NEXT: [[M_A:%.*]] = call i8* @llvm.ptr.annotation.p0i8(i8* nonnull [[M_I8]], i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str1, i64 0, i64 0), i32 2, i8* null)
|
||||
; CHECK-NEXT: [[M_X:%.*]] = bitcast i8* [[M_A]] to i64*
|
||||
; CHECK-NEXT: [[OBJSZ:%.*]] = call i64 @llvm.objectsize.i64.p0i8(i8* [[C:%.*]], i1 false, i1 false, i1 false)
|
||||
; CHECK-NEXT: store i64 [[OBJSZ]], i64* [[M_X]], align 4
|
||||
@ -44,7 +44,7 @@ entry:
|
||||
call void @llvm.lifetime.end.p0i8(i64 1, i8* %dummy)
|
||||
|
||||
%m_i8 = bitcast i64* %m to i8*
|
||||
%m_a = call i8* @llvm.ptr.annotation.p0i8(i8* %m_i8, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str1, i32 0, i32 0), i32 2)
|
||||
%m_a = call i8* @llvm.ptr.annotation.p0i8(i8* %m_i8, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str1, i32 0, i32 0), i32 2, i8* null)
|
||||
%m_x = bitcast i8* %m_a to i64*
|
||||
%objsz = call i64 @llvm.objectsize.i64.p0i8(i8* %c, i1 false)
|
||||
store i64 %objsz, i64* %m_x
|
||||
@ -64,7 +64,7 @@ entry:
|
||||
|
||||
declare i64 @llvm.objectsize.i64.p0i8(i8*, i1)
|
||||
declare i32 @llvm.annotation.i32(i32, i8*, i8*, i32)
|
||||
declare i8* @llvm.ptr.annotation.p0i8(i8*, i8*, i8*, i32)
|
||||
declare i8* @llvm.ptr.annotation.p0i8(i8*, i8*, i8*, i32, i8*)
|
||||
|
||||
declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture)
|
||||
declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture)
|
||||
|
Loading…
Reference in New Issue
Block a user