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

Reply via email to