Fix ARM FastISel PIC function call.
authorLogan Chien <tzuhsiang.chien@gmail.com>
Thu, 22 Aug 2013 12:08:04 +0000 (12:08 +0000)
committerLogan Chien <tzuhsiang.chien@gmail.com>
Thu, 22 Aug 2013 12:08:04 +0000 (12:08 +0000)
The function call to external function should come with PLT relocation
type if the PIC relocation model is used.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@189002 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/ARM/ARMFastISel.cpp
test/CodeGen/ARM/pic.ll [new file with mode: 0644]

index f4aaf09038a4ff5331cd93909a4bb211a0e90a8b..628b51414081cdbd6bd0a641a053b7382f75cb40 100644 (file)
@@ -2460,15 +2460,22 @@ bool ARMFastISel::SelectCall(const Instruction *I,
   MachineInstrBuilder MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt,
                                     DL, TII.get(CallOpc));
 
+  unsigned char OpFlags = 0;
+
+  // Add MO_PLT for global address or external symbol in the PIC relocation
+  // model.
+  if (Subtarget->isTargetELF() && TM.getRelocationModel() == Reloc::PIC_)
+    OpFlags = ARMII::MO_PLT;
+
   // ARM calls don't take a predicate, but tBL / tBLX do.
   if(isThumb2)
     AddDefaultPred(MIB);
   if (UseReg)
     MIB.addReg(CalleeReg);
   else if (!IntrMemName)
-    MIB.addGlobalAddress(GV, 0, 0);
+    MIB.addGlobalAddress(GV, 0, OpFlags);
   else
-    MIB.addExternalSymbol(IntrMemName, 0);
+    MIB.addExternalSymbol(IntrMemName, OpFlags);
 
   // Add implicit physical register uses to the call.
   for (unsigned i = 0, e = RegArgs.size(); i != e; ++i)
diff --git a/test/CodeGen/ARM/pic.ll b/test/CodeGen/ARM/pic.ll
new file mode 100644 (file)
index 0000000..32cea50
--- /dev/null
@@ -0,0 +1,23 @@
+; Check the function call in PIC relocation model.
+
+; If the relocation model is PIC, then the "bl" instruction for the function
+; call to the external function should come with PLT fixup type.
+
+; RUN:  llc < %s -mtriple=armv7-unknown-linux-gnueabi \
+; RUN:           -relocation-model=pic -fast-isel \
+; RUN:    | FileCheck %s
+
+define void @test() {
+entry:
+
+  %0 = call i32 @get()
+; CHECK: bl get(PLT)
+
+  call void @put(i32 %0)
+; CHECK: bl put(PLT)
+
+  ret void
+}
+
+declare i32 @get()
+declare void @put(i32)