diff options
-rw-r--r-- | include/clang/Basic/Attr.td | 5 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenModule.cpp | 3 | ||||
-rw-r--r-- | lib/Sema/SemaDeclAttr.cpp | 17 | ||||
-rw-r--r-- | test/CodeGen/attr-minsize.c | 26 | ||||
-rw-r--r-- | test/CodeGen/attr-minsize.cpp | 75 | ||||
-rw-r--r-- | test/CodeGenObjC/attr-minsize.m | 12 | ||||
-rw-r--r-- | test/Sema/attr-minsize.c | 5 |
7 files changed, 117 insertions, 26 deletions
diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td index 738b460b5a..bfe8093079 100644 --- a/include/clang/Basic/Attr.td +++ b/include/clang/Basic/Attr.td @@ -341,6 +341,11 @@ def Final : InheritableAttr { let SemaHandler = 0; } +def MinSize : InheritableAttr { + let Spellings = [GNU<"minsize">]; + let Subjects = [Function]; +} + def Format : InheritableAttr { let Spellings = [GNU<"format">]; let Args = [StringArgument<"Type">, IntArgument<"FormatIdx">, diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 9617de8eb7..11991124ee 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -583,6 +583,9 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D, if (D->hasAttr<ColdAttr>()) F->addFnAttr(llvm::Attributes::OptimizeForSize); + if (D->hasAttr<MinSizeAttr>()) + F->addFnAttr(llvm::Attributes::MinSize); + if (isa<CXXConstructorDecl>(D) || isa<CXXDestructorDecl>(D)) F->setUnnamedAddr(true); diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index df4757e4d2..6db30bea9d 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -1523,6 +1523,20 @@ static void handleAliasAttr(Sema &S, Decl *D, const AttributeList &Attr) { Str->getString())); } +static void handleMinSizeAttr(Sema &S, Decl *D, const AttributeList &Attr) { + // Check the attribute arguments. + if (!checkAttributeNumArgs(S, Attr, 0)) + return; + + if (!isa<FunctionDecl>(D) && !isa<ObjCMethodDecl>(D)) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunctionOrMethod; + return; + } + + D->addAttr(::new (S.Context) MinSizeAttr(Attr.getRange(), S.Context)); +} + static void handleColdAttr(Sema &S, Decl *D, const AttributeList &Attr) { // Check the attribute arguments. if (!checkAttributeNumArgs(S, Attr, 0)) @@ -4285,6 +4299,9 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_ExtVectorType: handleExtVectorTypeAttr(S, scope, D, Attr); break; + case AttributeList::AT_MinSize: + handleMinSizeAttr(S, D, Attr); + break; case AttributeList::AT_Format: handleFormatAttr (S, D, Attr); break; case AttributeList::AT_FormatArg: handleFormatArgAttr (S, D, Attr); break; case AttributeList::AT_CUDAGlobal: handleGlobalAttr (S, D, Attr); break; diff --git a/test/CodeGen/attr-minsize.c b/test/CodeGen/attr-minsize.c deleted file mode 100644 index dd260e43e0..0000000000 --- a/test/CodeGen/attr-minsize.c +++ /dev/null @@ -1,26 +0,0 @@ -// RUN: %clang_cc1 -Oz -emit-llvm %s -o - | FileCheck %s -check-prefix=Oz -// RUN: %clang_cc1 -O0 -emit-llvm %s -o - | FileCheck %s -check-prefix=OTHER -// RUN: %clang_cc1 -O1 -emit-llvm %s -o - | FileCheck %s -check-prefix=OTHER -// RUN: %clang_cc1 -O2 -emit-llvm %s -o - | FileCheck %s -check-prefix=OTHER -// RUN: %clang_cc1 -O3 -emit-llvm %s -o - | FileCheck %s -check-prefix=OTHER -// RUN: %clang_cc1 -Os -emit-llvm %s -o - | FileCheck %s -check-prefix=OTHER -// Check that we set the minsize attribute on each function -// when Oz optimization level is set. - -int test1() { - return 42; -// Oz: @test1{{.*}}minsize -// Oz: ret -// OTHER: @test1 -// OTHER-NOT: minsize -// OTHER: ret -} - -int test2() { - return 42; -// Oz: @test2{{.*}}minsize -// Oz: ret -// OTHER: @test2 -// OTHER-NOT: minsize -// OTHER: ret -} diff --git a/test/CodeGen/attr-minsize.cpp b/test/CodeGen/attr-minsize.cpp new file mode 100644 index 0000000000..a422a62f25 --- /dev/null +++ b/test/CodeGen/attr-minsize.cpp @@ -0,0 +1,75 @@ +// RUN: %clang_cc1 -Oz -emit-llvm %s -o - | FileCheck %s -check-prefix=Oz +// RUN: %clang_cc1 -O0 -emit-llvm %s -o - | FileCheck %s -check-prefix=OTHER +// RUN: %clang_cc1 -O1 -emit-llvm %s -o - | FileCheck %s -check-prefix=OTHER +// RUN: %clang_cc1 -O2 -emit-llvm %s -o - | FileCheck %s -check-prefix=OTHER +// RUN: %clang_cc1 -O3 -emit-llvm %s -o - | FileCheck %s -check-prefix=OTHER +// RUN: %clang_cc1 -Os -emit-llvm %s -o - | FileCheck %s -check-prefix=OTHER +// Check that we set the minsize attribute on each function +// when Oz optimization level is set. + +int test1() { + return 42; +// Oz: @{{.*}}test1{{.*}}minsize +// Oz: ret +// OTHER: @{{.*}}test1 +// OTHER-NOT: minsize +// OTHER: ret +} + +int test2() { + return 42; +// Oz: @{{.*}}test2{{.*}}minsize +// Oz: ret +// OTHER: @{{.*}}test2 +// OTHER-NOT: minsize +// OTHER: ret +} + +__attribute__((minsize)) +int test3() { + return 42; +// Oz: @{{.*}}test3{{.*}}minsize +// OTHER: @{{.*}}test3{{.*}}minsize +} + +// Check that the minsize attribute is well propagated through +// template instantiation + +template<typename T> +__attribute__((minsize)) +void test4(T arg) { + return; +} + +template +void test4<int>(int arg); +// Oz: define{{.*}}void @{{.*}}test4 +// Oz: minsize +// OTHER: define{{.*}}void @{{.*}}test4 +// OTHER: minsize + +template +void test4<float>(float arg); +// Oz: define{{.*}}void @{{.*}}test4 +// Oz: minsize +// OTHER: define{{.*}}void @{{.*}}test4 +// OTHER: minsize + +template<typename T> +void test5(T arg) { + return; +} + +template +void test5<int>(int arg); +// Oz: define{{.*}}void @{{.*}}test5 +// Oz: minsize +// OTHER: define{{.*}}void @{{.*}}test5 +// OTHER-NOT: minsize + +template +void test5<float>(float arg); +// Oz: define{{.*}}void @{{.*}}test5 +// Oz: minsize +// OTHER: define{{.*}}void @{{.*}}test5 +// OTHER-NOT: minsize diff --git a/test/CodeGenObjC/attr-minsize.m b/test/CodeGenObjC/attr-minsize.m new file mode 100644 index 0000000000..f46107eca6 --- /dev/null +++ b/test/CodeGenObjC/attr-minsize.m @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s + +@interface Test +- (void)test; +@end + +@implementation Test +- (void)test __attribute__((minsize)) { + // CHECK: define{{.*}}Test test + // CHECK: minsize +} +@end diff --git a/test/Sema/attr-minsize.c b/test/Sema/attr-minsize.c new file mode 100644 index 0000000000..7b1c6ae66f --- /dev/null +++ b/test/Sema/attr-minsize.c @@ -0,0 +1,5 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +int foo() __attribute__((__minsize__)); + +int var1 __attribute__((__minsize__)); // expected-error{{'__minsize__' attribute only applies to functions and methods}} |