From: Saleem Abdulrasool Date: Mon, 7 Jul 2014 05:18:35 +0000 (+0000) Subject: ARM: properly lower dllimport'ed global values X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=763f9a50a5234fb27c0f03efd54b87ccdd7ca080;p=platform%2Fupstream%2Fllvm.git ARM: properly lower dllimport'ed global values This completes the handling for DLL import storage symbols when lowering instructions. A DLL import storage symbol must have an additional load performed prior to use. This is applicable to variables and functions. This is particularly important for non-function symbols as it is possible to handle function references by emitting a thunk which performs the translation from the unprefixed __imp_ symbol to the proper symbol (although, this is a non-optimal lowering). For a variable symbol, no such thunk can be accommodated. llvm-svn: 212431 --- diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp index f0fab69..4bfa5a8 100644 --- a/llvm/lib/Target/ARM/ARMISelLowering.cpp +++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp @@ -1654,6 +1654,19 @@ ARMTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, assert(Subtarget->isTargetMachO() && "WrapperPIC use on non-MachO?"); Callee = DAG.getNode(ARMISD::WrapperPIC, dl, getPointerTy(), DAG.getTargetGlobalAddress(GV, dl, getPointerTy())); + } else if (Subtarget->isTargetCOFF()) { + assert(Subtarget->isTargetWindows() && + "Windows is the only supported COFF target"); + unsigned TargetFlags = GV->hasDLLImportStorageClass() + ? ARMII::MO_DLLIMPORT + : ARMII::MO_NO_FLAG; + Callee = DAG.getTargetGlobalAddress(GV, dl, getPointerTy(), /*Offset=*/0, + TargetFlags); + if (GV->hasDLLImportStorageClass()) + Callee = DAG.getLoad(getPointerTy(), dl, DAG.getEntryNode(), + DAG.getNode(ARMISD::Wrapper, dl, getPointerTy(), + Callee), MachinePointerInfo::getGOT(), + false, false, false, 0); } else { // On ELF targets for PIC code, direct calls should go through the PLT unsigned OpFlags = 0; @@ -2489,15 +2502,23 @@ SDValue ARMTargetLowering::LowerGlobalAddressWindows(SDValue Op, "Windows on ARM expects to use movw/movt"); const GlobalValue *GV = cast(Op)->getGlobal(); + const ARMII::TOF TargetFlags = + (GV->hasDLLImportStorageClass() ? ARMII::MO_DLLIMPORT : ARMII::MO_NO_FLAG); EVT PtrVT = getPointerTy(); + SDValue Result; SDLoc DL(Op); ++NumMovwMovt; // FIXME: Once remat is capable of dealing with instructions with register // operands, expand this into two nodes. - return DAG.getNode(ARMISD::Wrapper, DL, PtrVT, - DAG.getTargetGlobalAddress(GV, DL, PtrVT)); + Result = DAG.getNode(ARMISD::Wrapper, DL, PtrVT, + DAG.getTargetGlobalAddress(GV, DL, PtrVT, /*Offset=*/0, + TargetFlags)); + if (GV->hasDLLImportStorageClass()) + Result = DAG.getLoad(PtrVT, DL, DAG.getEntryNode(), Result, + MachinePointerInfo::getGOT(), false, false, false, 0); + return Result; } SDValue ARMTargetLowering::LowerGLOBAL_OFFSET_TABLE(SDValue Op, diff --git a/llvm/test/CodeGen/ARM/Windows/dllimport.ll b/llvm/test/CodeGen/ARM/Windows/dllimport.ll new file mode 100644 index 0000000..bc737bd --- /dev/null +++ b/llvm/test/CodeGen/ARM/Windows/dllimport.ll @@ -0,0 +1,61 @@ +; RUN: llc -mtriple thumbv7-windows -filetype asm -o - %s | FileCheck %s + +; ModuleID = 'dllimport.c' + +@var = external dllimport global i32 +@ext = external global i32 +declare dllimport arm_aapcs_vfpcc i32 @external() +declare arm_aapcs_vfpcc i32 @internal() + +define arm_aapcs_vfpcc i32 @get_var() { + %1 = load i32* @var, align 4 + ret i32 %1 +} + +; CHECK-LABEL: get_var +; CHECK: movw r0, :lower16:__imp_var +; CHECK: movt r0, :upper16:__imp_var +; CHECK: ldr r0, [r0] +; CHECK: ldr r0, [r0] +; CHECK: bx lr + +define arm_aapcs_vfpcc i32 @get_ext() { + %1 = load i32* @ext, align 4 + ret i32 %1 +} + +; CHECK-LABEL: get_ext +; CHECK: movw r0, :lower16:ext +; CHECK: movt r0, :upper16:ext +; CHECK: ldr r0, [r0] +; CHECK: bx lr + +define arm_aapcs_vfpcc i32* @get_var_pointer() { + ret i32* @var +} + +; CHECK-LABEL: get_var_pointer +; CHECK: movw r0, :lower16:__imp_var +; CHECK: movt r0, :upper16:__imp_var +; CHECK: ldr r0, [r0] +; CHECK: bx lr + +define arm_aapcs_vfpcc i32 @call_external() { + %call = tail call arm_aapcs_vfpcc i32 @external() + ret i32 %call +} + +; CHECK-LABEL: call_external +; CHECK: movw r0, :lower16:__imp_external +; CHECK: movt r0, :upper16:__imp_external +; CHECK: ldr r0, [r0] +; CHECK: bx r0 + +define arm_aapcs_vfpcc i32 @call_internal() { + %call = tail call arm_aapcs_vfpcc i32 @internal() + ret i32 %call +} + +; CHECK-LABEL: call_internal +; CHECK: b internal +