atanasyan created this revision. atanasyan added a project: clang. Herald added subscribers: arichardson, javed.absar.
This patch adds support for the `long_call`, `far`, and `near` attributes for MIPS targets. The `long_call` and `far` attributes are synonyms. All these attributes override `-mlong-calls` / `-mno-long-calls` command line options for particular function. The main non-trivial part is the change in `CodeGenModule::ConstructAttributeList` routine. It is not enough to configure attributes in `MIPSTargetCodeGenInfo::setTargetAttributes` because this method applied to the function definitions only while we need to configure the attributes for function declarations as well. Repository: rL LLVM https://reviews.llvm.org/D35479 Files: include/clang/Basic/Attr.td include/clang/Basic/AttrDocs.td lib/CodeGen/CGCall.cpp 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,13 @@ +// 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(); 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 63 attributes: // CHECK-NEXT: AMDGPUFlatWorkGroupSize (SubjectMatchRule_function) // CHECK-NEXT: AMDGPUNumSGPR (SubjectMatchRule_function) // CHECK-NEXT: AMDGPUNumVGPR (SubjectMatchRule_function) @@ -31,6 +31,7 @@ // 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: 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,19 @@ +// 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: call void @foo1() [[LONGCALL:#[0-9]+]] + +// CHECK: declare void @foo1() [[LONGDECL:#[0-9]+]] + +// CHECK: attributes [[FAR]] = { {{.*}} "long-call" {{.*}} } +// CHECK: attributes [[NEAR]] = { {{.*}} "near-call" {{.*}} } +// CHECK: attributes [[LONGDECL]] = { {{.*}} "long-call" {{.*}} } +// CHECK: attributes [[LONGCALL]] = { "long-call" } Index: lib/Sema/SemaDeclAttr.cpp =================================================================== --- lib/Sema/SemaDeclAttr.cpp +++ lib/Sema/SemaDeclAttr.cpp @@ -5950,6 +5950,9 @@ case AttributeList::AT_NoMicroMips: handleSimpleAttribute<NoMicroMipsAttr>(S, D, Attr); break; + case AttributeList::AT_MipsLongCall: + handleSimpleAttribute<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,13 @@ else if (FD->hasAttr<NoMicroMipsAttr>()) Fn->addFnAttr("nomicromips"); + if (const auto *LongCallAttr = FD->getAttr<MipsLongCallAttr>()) { + if (LongCallAttr->longCall()) + Fn->addFnAttr("long-call"); + else if (LongCallAttr->nearCall()) + Fn->addFnAttr("near-call"); + } + const MipsInterruptAttr *Attr = FD->getAttr<MipsInterruptAttr>(); if (!Attr) return; Index: lib/CodeGen/CGCall.cpp =================================================================== --- lib/CodeGen/CGCall.cpp +++ lib/CodeGen/CGCall.cpp @@ -1802,6 +1802,13 @@ if (TargetDecl->hasAttr<ConvergentAttr>()) FuncAttrs.addAttribute(llvm::Attribute::Convergent); + if (const auto *LongCallAttr = TargetDecl->getAttr<MipsLongCallAttr>()) { + if (LongCallAttr->longCall()) + FuncAttrs.addAttribute("long-call"); + else if (LongCallAttr->nearCall()) + FuncAttrs.addAttribute("near-call"); + } + if (const FunctionDecl *Fn = dyn_cast<FunctionDecl>(TargetDecl)) { AddAttributesFromFunctionProtoType( getContext(), FuncAttrs, Fn->getType()->getAs<FunctionProtoType>()); Index: include/clang/Basic/AttrDocs.td =================================================================== --- include/clang/Basic/AttrDocs.td +++ include/clang/Basic/AttrDocs.td @@ -1323,6 +1323,20 @@ }]; } +def MipsLongCallDocs : Documentation { + let Category = DocCatFunction; + let Content = [{ +Clang supports the GNU style ``__attribute__(("CALL STYLE"))`` +attributes on MIPS targets. Where "CALL STYLE" is either ``long_call`` or +``far`` or ``near``. These attributes may be attached to a function declaration +and override the ``-mlong-calls`` command line switch. The ``long_call`` +and ``far`` attributes are synonyms and disable using the ``jal`` instruction +to call the function. The ``near`` attribute has the opposite effect - even +if code compiled using ``-mlong-calls`` switch, it forces compiler to use +the ``jal`` instruction to call the function. + }]; +} + 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,14 @@ let Documentation = [MicroMipsDocs]; } +def MipsLongCall : InheritableAttr, TargetSpecificAttr<TargetMips> { + let Spellings = [GCC<"long_call">, GCC<"far">, GCC<"near">]; + let Subjects = SubjectList<[Function]>; + let Accessors = [Accessor<"longCall", [GCC<"long_call">, GCC<"far">]>, + Accessor<"nearCall", [GCC<"near">]>]; + let Documentation = [MipsLongCallDocs]; +} + 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