OSDN Git Service

[mips] Support `long_call/far/near` attributes passed by front-end
[android-x86/external-llvm.git] / lib / Target / Mips / MipsISelLowering.cpp
index 20319f8..dd41fef 100644 (file)
@@ -3152,15 +3152,30 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
   // The long-calls feature is ignored in case of PIC.
   // While we do not support -mshared / -mno-shared properly,
   // ignore long-calls in case of -mabicalls too.
-  if (Subtarget.useLongCalls() && !Subtarget.isABICalls() && !IsPIC) {
-    // Get the address of the callee into a register to prevent
-    // using of the `jal` instruction for the direct call.
-    if (auto *N = dyn_cast<GlobalAddressSDNode>(Callee))
-      Callee = Subtarget.hasSym32() ? getAddrNonPIC(N, SDLoc(N), Ty, DAG)
-                                    : getAddrNonPICSym64(N, SDLoc(N), Ty, DAG);
-    else if (auto *N = dyn_cast<ExternalSymbolSDNode>(Callee))
-      Callee = Subtarget.hasSym32() ? getAddrNonPIC(N, SDLoc(N), Ty, DAG)
-                                    : getAddrNonPICSym64(N, SDLoc(N), Ty, DAG);
+  if (!Subtarget.isABICalls() && !IsPIC) {
+    // If the function should be called using "long call",
+    // get its address into a register to prevent using
+    // of the `jal` instruction for the direct call.
+    if (auto *N = dyn_cast<ExternalSymbolSDNode>(Callee)) {
+      if (Subtarget.useLongCalls())
+        Callee = Subtarget.hasSym32()
+                     ? getAddrNonPIC(N, SDLoc(N), Ty, DAG)
+                     : getAddrNonPICSym64(N, SDLoc(N), Ty, DAG);
+    } else if (auto *N = dyn_cast<GlobalAddressSDNode>(Callee)) {
+      bool UseLongCalls = Subtarget.useLongCalls();
+      // If the function has long-call/far/near attribute
+      // it overrides command line switch pased to the backend.
+      if (auto *F = dyn_cast<Function>(N->getGlobal())) {
+        if (F->hasFnAttribute("long-call"))
+          UseLongCalls = true;
+        else if (F->hasFnAttribute("short-call"))
+          UseLongCalls = false;
+      }
+      if (UseLongCalls)
+        Callee = Subtarget.hasSym32()
+                     ? getAddrNonPIC(N, SDLoc(N), Ty, DAG)
+                     : getAddrNonPICSym64(N, SDLoc(N), Ty, DAG);
+    }
   }
 
   if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {