(AM.Base.Reg != 0 || AM.IndexReg != 0))
return false;
- // Can't handle DLL Import.
- if (GV->hasDLLImportStorageClass())
- return false;
-
// Can't handle TLS.
if (const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV))
if (GVar->isThreadLocal())
// Okay, we've committed to selecting this global. Set up the basic address.
AM.GV = GV;
- // No ABI requires an extra load for anything other than DLLImport, which
- // we rejected above. Return a direct reference to the global.
+ // Return a direct reference to the global. Fastisel can handle calls to
+ // functions that require loads, such as dllimport and nonlazybind
+ // functions.
if (Subtarget->isPICStyleRIPRel()) {
// Use rip-relative addressing if we can. Above we verified that the
// base and index registers are unused.
} else {
// Direct call.
assert(GV && "Not a direct call");
- unsigned CallOpc = Is64Bit ? X86::CALL64pcrel32 : X86::CALLpcrel32;
-
// See if we need any target-specific flags on the GV operand.
unsigned char OpFlags = Subtarget->classifyGlobalFunctionReference(GV);
// Ignore NonLazyBind attribute in FastISel
if (OpFlags == X86II::MO_GOTPCREL)
OpFlags = 0;
+ // This will be a direct call, or an indirect call through memory for
+ // NonLazyBind calls or dllimport calls.
+ bool NeedLoad = OpFlags == X86II::MO_DLLIMPORT;
+ unsigned CallOpc = NeedLoad
+ ? (Is64Bit ? X86::CALL64m : X86::CALL32m)
+ : (Is64Bit ? X86::CALL64pcrel32 : X86::CALLpcrel32);
+
MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(CallOpc));
+ if (NeedLoad)
+ MIB.addReg(Is64Bit ? X86::RIP : 0).addImm(1).addReg(0);
if (Symbol)
MIB.addSym(Symbol, OpFlags);
else
MIB.addGlobalAddress(GV, 0, OpFlags);
+ if (NeedLoad)
+ MIB.addReg(0);
}
// Add a register mask operand representing the call-preserved registers.
if (TM.shouldAssumeDSOLocal(M, GV))
return X86II::MO_NO_FLAG;
- assert(!isTargetCOFF());
+ if (isTargetCOFF()) {
+ assert(GV->hasDLLImportStorageClass() &&
+ "shouldAssumeDSOLocal gave inconsistent answer");
+ return X86II::MO_DLLIMPORT;
+ }
+
const Function *F = dyn_cast_or_null<Function>(GV);
if (isTargetELF()) {
; RUN: llc -mtriple x86_64-pc-win32 < %s | FileCheck %s
; RUN: llc -mtriple x86_64-pc-mingw32 < %s | FileCheck %s
;
-; RUN: llc -mtriple x86_64-pc-mingw32 -O0 < %s | FileCheck %s -check-prefix=FAST
+; RUN: llc -mtriple x86_64-pc-mingw32 -O0 < %s | FileCheck %s
+; RUN: llc -mtriple x86_64-pc-windows-msvc -O0 < %s | FileCheck %s
; PR6275
;
; RUN: opt -mtriple x86_64-pc-win32 -O3 -S < %s | FileCheck %s -check-prefix=OPT
define void @use() nounwind {
; CHECK: callq *__imp_fun(%rip)
-; FAST: movq __imp_fun(%rip), [[R:%[a-z]{3}]]
-; FAST-NEXT: callq *[[R]]
call void @fun()
; CHECK: callq *__imp_inline1(%rip)
; RUN: llc -mtriple i386-pc-win32 < %s | FileCheck %s
; RUN: llc -mtriple i386-pc-mingw32 < %s | FileCheck %s
;
-; RUN: llc -mtriple i386-pc-mingw32 -O0 < %s | FileCheck %s -check-prefix=FAST
+; RUN: llc -mtriple i386-pc-mingw32 -O0 < %s | FileCheck %s
+; RUN: llc -mtriple i386-pc-windows-msvc -O0 < %s | FileCheck %s
; PR6275
;
; RUN: opt -mtriple i386-pc-win32 -O3 -S < %s | FileCheck %s -check-prefix=OPT
define void @use() nounwind {
; CHECK: calll *__imp__fun
-; FAST: movl __imp__fun, [[R:%[a-z]{3}]]
-; FAST-NEXT: calll *[[R]]
call void @fun()
; CHECK: calll *__imp__inline1
--- /dev/null
+; RUN: llc -fast-isel -O0 -code-model=large -mcpu=generic -mtriple=x86_64-apple-darwin10 -relocation-model=pic < %s | FileCheck %s
+
+; Check that fast-isel cleans up when it fails to lower a call instruction.
+define void @fastiselcall() {
+entry:
+ %call = call i32 @targetfn(i32 42)
+ ret void
+; CHECK-LABEL: test5:
+; Local value area is still there:
+; CHECK: movl $42, {{%[a-z]+}}
+; Fast-ISel's arg mov is not here:
+; CHECK-NOT: movl $42, (%esp)
+; SDag-ISel's arg mov:
+; CHECK: movabsq $_targetfn, %[[REG:[^ ]*]]
+; CHECK: movl $42, %edi
+; CHECK: callq *%[[REG]]
+
+}
+declare i32 @targetfn(i32)
; CHECK: addl $28
}
declare fastcc void @test4fastccsret(%struct.a* sret)
-
-
-; Check that fast-isel cleans up when it fails to lower a call instruction.
-define void @test5() {
-entry:
- %call = call i32 @test5dllimport(i32 42)
- ret void
-; CHECK-LABEL: test5:
-; Local value area is still there:
-; CHECK: movl $42, {{%[a-z]+}}
-; Fast-ISel's arg push is not here:
-; CHECK-NOT: movl $42, (%esp)
-; SDag-ISel's arg push:
-; CHECK: movl %esp, [[REGISTER:%[a-z]+]]
-; CHECK: movl $42, ([[REGISTER]])
-; CHECK: movl L_test5dllimport$non_lazy_ptr-L8$pb(%eax), %eax
-
-}
-declare dllimport i32 @test5dllimport(i32)