// Can't handle inline asm.
if (isa<InlineAsm>(Callee)) return false;
- // Only handle global variable Callees.
- const GlobalValue *GV = dyn_cast<GlobalValue>(Callee);
- if (!GV)
- return false;
-
// Check the calling convention.
ImmutableCallSite CS(CI);
CallingConv::ID CC = CS.getCallingConv();
// Issue the call.
MachineInstrBuilder MIB;
+ const GlobalValue *GV = dyn_cast<GlobalValue>(Callee);
unsigned CallOpc = ARMSelectCallOp(GV);
+ unsigned CalleeReg = 0;
+
+ if (!GV){
+ CallOpc = isThumb2 ? ARM::tBLXr : ARM::BLX;
+ CalleeReg = getRegForValue(Callee);
+ if (CalleeReg == 0) return false;
+ }
+
// Explicitly adding the predicate here.
if(isThumb2) {
// Explicitly adding the predicate here.
MIB = AddDefaultPred(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL,
TII.get(CallOpc)));
- if (!IntrMemName)
+ if (!GV)
+ MIB.addReg(CalleeReg);
+ else if (!IntrMemName)
MIB.addGlobalAddress(GV, 0, 0);
else
MIB.addExternalSymbol(IntrMemName, 0);
} else {
- if (!IntrMemName)
+ if (!GV)
+ MIB = AddDefaultPred(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL,
+ TII.get(CallOpc))
+ .addReg(CalleeReg));
+ else if (!IntrMemName)
// Explicitly adding the predicate here.
MIB = AddDefaultPred(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL,
TII.get(CallOpc))
}
declare i32 @bar(i8 zeroext, i8 zeroext, i8 zeroext, i8 zeroext, i8 zeroext, i8 zeroext)
+
+define i32 @bar0(i32 %i) nounwind {
+ ret i32 0
+}
+
+define void @foo3() uwtable {
+; ARM: movw r0, #0
+; ARM: movw r1, :lower16:_bar0
+; ARM: movt r1, :upper16:_bar0
+; ARM: blx r1
+; THUMB: movs r0, #0
+; THUMB: movw r1, :lower16:_bar0
+; THUMB: movt r1, :upper16:_bar0
+; THUMB: blx r1
+ %fptr = alloca i32 (i32)*, align 8
+ store i32 (i32)* @bar0, i32 (i32)** %fptr, align 8
+ %1 = load i32 (i32)** %fptr, align 8
+ %call = call i32 %1(i32 0)
+ ret void
+}