atanasyan updated this revision to Diff 107193. atanasyan added a comment. Addressed review comment:
- Split MipsLongCall into a couple of attributes MipsLongCall and MipsShortCall. - Change the documentation wording. - Keep the attributes handling in the setTargetAttributes. - Show error in case of combining incompatible attributes. Repository: rL LLVM https://reviews.llvm.org/D35479 Files: include/clang/Basic/Attr.td include/clang/Basic/AttrDocs.td lib/CodeGen/CodeGenModule.cpp lib/CodeGen/CodeGenModule.h lib/CodeGen/TargetInfo.cpp lib/Sema/SemaDeclAttr.cpp test/CodeGen/long-call-attr.c test/Misc/pragma-attribute-supported-attributes-list.test test/Sema/attr-long-call.c
Index: test/Sema/attr-long-call.c =================================================================== --- /dev/null +++ test/Sema/attr-long-call.c @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -triple mips-linux-gnu -fsyntax-only -verify %s + +__attribute__((long_call(0))) void foo1(); // expected-error {{'long_call' attribute takes no arguments}} +__attribute__((far(0))) void foo2(); // expected-error {{'far' attribute takes no arguments}} +__attribute__((near(0))) void foo3(); // expected-error {{'near' attribute takes no arguments}} + +__attribute((long_call)) int a; // expected-warning {{attribute only applies to functions}} +__attribute((far)) int a; // expected-warning {{attribute only applies to functions}} +__attribute((near)) int a; // expected-warning {{attribute only applies to functions}} + +__attribute((long_call)) void foo4(); +__attribute((far)) void foo5(); +__attribute((near)) void foo6(); + +__attribute((long_call, far)) void foo7(); + +__attribute((far, near)) void foo8(); // expected-error {{'far' and 'near' attributes are not compatible}} \ + // expected-note {{conflicting attribute is here}} Index: test/Misc/pragma-attribute-supported-attributes-list.test =================================================================== --- test/Misc/pragma-attribute-supported-attributes-list.test +++ test/Misc/pragma-attribute-supported-attributes-list.test @@ -2,7 +2,7 @@ // The number of supported attributes should never go down! -// CHECK: #pragma clang attribute supports 62 attributes: +// CHECK: #pragma clang attribute supports 64 attributes: // CHECK-NEXT: AMDGPUFlatWorkGroupSize (SubjectMatchRule_function) // CHECK-NEXT: AMDGPUNumSGPR (SubjectMatchRule_function) // CHECK-NEXT: AMDGPUNumVGPR (SubjectMatchRule_function) @@ -31,6 +31,8 @@ // CHECK-NEXT: InternalLinkage (SubjectMatchRule_variable, SubjectMatchRule_function, SubjectMatchRule_record) // CHECK-NEXT: LTOVisibilityPublic (SubjectMatchRule_record) // CHECK-NEXT: MicroMips (SubjectMatchRule_function) +// CHECK-NEXT: MipsLongCall (SubjectMatchRule_function) +// CHECK-NEXT: MipsShortCall (SubjectMatchRule_function) // CHECK-NEXT: NoDebug (SubjectMatchRule_hasType_functionType, SubjectMatchRule_objc_method, SubjectMatchRule_variable_not_is_parameter) // CHECK-NEXT: NoDuplicate (SubjectMatchRule_function) // CHECK-NEXT: NoMicroMips (SubjectMatchRule_function) Index: test/CodeGen/long-call-attr.c =================================================================== --- /dev/null +++ test/CodeGen/long-call-attr.c @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -triple mips-linux-gnu -emit-llvm -o - %s | FileCheck %s + +void __attribute__((long_call)) foo1 (void); + +void __attribute__((far)) foo2 (void) {} + +// CHECK: define void @foo2() [[FAR:#[0-9]+]] + +void __attribute__((near)) foo3 (void) { foo1(); } + +// CHECK: define void @foo3() [[NEAR:#[0-9]+]] + +// CHECK: declare void @foo1() [[LONGDECL:#[0-9]+]] + +// CHECK: attributes [[FAR]] = { {{.*}} "long-call" {{.*}} } +// CHECK: attributes [[NEAR]] = { {{.*}} "short-call" {{.*}} } +// CHECK: attributes [[LONGDECL]] = { {{.*}} "long-call" {{.*}} } Index: lib/Sema/SemaDeclAttr.cpp =================================================================== --- lib/Sema/SemaDeclAttr.cpp +++ lib/Sema/SemaDeclAttr.cpp @@ -5965,6 +5965,14 @@ case AttributeList::AT_NoMicroMips: handleSimpleAttribute<NoMicroMipsAttr>(S, D, Attr); break; + case AttributeList::AT_MipsLongCall: + handleSimpleAttributeWithExclusions<MipsLongCallAttr, MipsShortCallAttr>( + S, D, Attr); + break; + case AttributeList::AT_MipsShortCall: + handleSimpleAttributeWithExclusions<MipsShortCallAttr, MipsLongCallAttr>( + S, D, Attr); + break; case AttributeList::AT_AMDGPUFlatWorkGroupSize: handleAMDGPUFlatWorkGroupSizeAttr(S, D, Attr); break; Index: lib/CodeGen/TargetInfo.cpp =================================================================== --- lib/CodeGen/TargetInfo.cpp +++ lib/CodeGen/TargetInfo.cpp @@ -6619,6 +6619,11 @@ else if (FD->hasAttr<NoMicroMipsAttr>()) Fn->addFnAttr("nomicromips"); + if (FD->hasAttr<MipsLongCallAttr>()) + Fn->addFnAttr("long-call"); + else if (FD->hasAttr<MipsShortCallAttr>()) + Fn->addFnAttr("short-call"); + const MipsInterruptAttr *Attr = FD->getAttr<MipsInterruptAttr>(); if (!Attr) return; Index: lib/CodeGen/CodeGenModule.h =================================================================== --- lib/CodeGen/CodeGenModule.h +++ lib/CodeGen/CodeGenModule.h @@ -1239,7 +1239,8 @@ /// Set function attributes for a function declaration. void SetFunctionAttributes(GlobalDecl GD, llvm::Function *F, - bool IsIncompleteFunction, bool IsThunk); + bool IsIncompleteFunction, bool IsThunk, + ForDefinition_t IsForDefinition); void EmitGlobalDefinition(GlobalDecl D, llvm::GlobalValue *GV = nullptr); Index: lib/CodeGen/CodeGenModule.cpp =================================================================== --- lib/CodeGen/CodeGenModule.cpp +++ lib/CodeGen/CodeGenModule.cpp @@ -1147,7 +1147,9 @@ void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, llvm::Function *F, bool IsIncompleteFunction, - bool IsThunk) { + bool IsThunk, + ForDefinition_t IsForDefinition) { + if (llvm::Intrinsic::ID IID = F->getIntrinsicID()) { // If this is an intrinsic function, set the function's attributes // to the intrinsic's attributes. @@ -1157,8 +1159,12 @@ const auto *FD = cast<FunctionDecl>(GD.getDecl()); - if (!IsIncompleteFunction) + if (!IsIncompleteFunction) { SetLLVMFunctionAttributes(FD, getTypes().arrangeGlobalDeclaration(GD), F); + // Setup target-specific attributes. + if (!IsForDefinition) + getTargetCodeGenInfo().setTargetAttributes(FD, F, *this); + } // Add the Returned attribute for "this", except for iOS 5 and earlier // where substantial code, including the libstdc++ dylib, was compiled with @@ -2123,7 +2129,8 @@ assert(F->getName() == MangledName && "name was uniqued!"); if (D) - SetFunctionAttributes(GD, F, IsIncompleteFunction, IsThunk); + SetFunctionAttributes(GD, F, IsIncompleteFunction, IsThunk, + IsForDefinition); if (ExtraAttrs.hasAttributes(llvm::AttributeList::FunctionIndex)) { llvm::AttrBuilder B(ExtraAttrs, llvm::AttributeList::FunctionIndex); F->addAttributes(llvm::AttributeList::FunctionIndex, B); Index: include/clang/Basic/AttrDocs.td =================================================================== --- include/clang/Basic/AttrDocs.td +++ include/clang/Basic/AttrDocs.td @@ -1323,6 +1323,24 @@ }]; } +def MipsCallStyleDocs : Documentation { + let Category = DocCatFunction; + let Content = [{ +Clang supports the ``__attribute__((long_call))``, ``__attribute__((far))``, +and ``__attribute__((near))`` attributes on MIPS targets. These attributes may +only be added to function declarations and change the code generated +by the compiler when directly calling the function. The ``near`` attribute +allows calls to the function to be made using the ``jal`` instruction, which +requires the function to be defined in the same 256MB segment as the caller. +The ``long_call`` and ``far`` attributes are synonyms and require the use +of a different call sequence that works regardless of the distance between +the functions. + +These attributes take priority over command line switches such +as ``-mlong-calls`` and ``-mno-long-calls``. + }]; +} + def AVRInterruptDocs : Documentation { let Category = DocCatFunction; let Content = [{ Index: include/clang/Basic/Attr.td =================================================================== --- include/clang/Basic/Attr.td +++ include/clang/Basic/Attr.td @@ -1188,6 +1188,18 @@ let Documentation = [MicroMipsDocs]; } +def MipsLongCall : InheritableAttr, TargetSpecificAttr<TargetMips> { + let Spellings = [GCC<"long_call">, GCC<"far">]; + let Subjects = SubjectList<[Function]>; + let Documentation = [MipsCallStyleDocs]; +} + +def MipsShortCall : InheritableAttr, TargetSpecificAttr<TargetMips> { + let Spellings = [GCC<"near">]; + let Subjects = SubjectList<[Function]>; + let Documentation = [MipsCallStyleDocs]; +} + def Mode : Attr { let Spellings = [GCC<"mode">]; let Subjects = SubjectList<[Var, Enum, TypedefName, Field], ErrorDiag,
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits