diff --git a/llvm/include/llvm/CodeGen/AsmPrinter.h b/llvm/include/llvm/CodeGen/AsmPrinter.h --- a/llvm/include/llvm/CodeGen/AsmPrinter.h +++ b/llvm/include/llvm/CodeGen/AsmPrinter.h @@ -437,7 +437,7 @@ virtual const MCExpr *lowerConstant(const Constant *CV); /// Print a general LLVM constant to the .s file. - void emitGlobalConstant(const DataLayout &DL, const Constant *CV); + virtual void emitGlobalConstant(const DataLayout &DL, const Constant *CV); /// Unnamed constant global variables solely contaning a pointer to /// another globals variable act like a global variable "proxy", or GOT diff --git a/llvm/lib/Target/X86/X86AsmPrinter.h b/llvm/lib/Target/X86/X86AsmPrinter.h --- a/llvm/lib/Target/X86/X86AsmPrinter.h +++ b/llvm/lib/Target/X86/X86AsmPrinter.h @@ -150,6 +150,9 @@ SMShadowTracker.emitShadowPadding(*OutStreamer, getSubtargetInfo()); } + /// This is used to lower certain X86 addrspacecasts. + void emitGlobalConstant(const DataLayout &DL, const Constant *CV) override; + bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, const char *ExtraCode, raw_ostream &O) override; bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, diff --git a/llvm/lib/Target/X86/X86AsmPrinter.cpp b/llvm/lib/Target/X86/X86AsmPrinter.cpp --- a/llvm/lib/Target/X86/X86AsmPrinter.cpp +++ b/llvm/lib/Target/X86/X86AsmPrinter.cpp @@ -11,6 +11,7 @@ // //===----------------------------------------------------------------------===// +#include "X86.h" #include "X86AsmPrinter.h" #include "MCTargetDesc/X86ATTInstPrinter.h" #include "MCTargetDesc/X86BaseInfo.h" @@ -108,6 +109,46 @@ } } +void X86AsmPrinter::emitGlobalConstant(const DataLayout &DL, const Constant *CV) { + // Use this function to emit special addrspacecasts. + if (!CV) { + AsmPrinter::emitGlobalConstant(DL, CV); + return; + } + + const ConstantExpr *CE = dyn_cast(CV); + + if (!CE || CE->getOpcode() != Instruction::AddrSpaceCast) { + AsmPrinter::emitGlobalConstant(DL, CV); + return; + } + + Constant *Op = CE->getOperand(0); + unsigned DstAS = CE->getType()->getPointerAddressSpace(); + unsigned SrcAS = Op->getType()->getPointerAddressSpace(); + + if (TM.isNoopAddrSpaceCast(SrcAS, DstAS)) { + // Remove the addrspacecast. + AsmPrinter::emitGlobalConstant(DL, Op); + return; + } + + const MCExpr *ME = AsmPrinter::lowerConstant(Op); + if ((SrcAS == 0 || SrcAS == X86AS::PTR32_UPTR) && DstAS == X86AS::PTR64) { + // For zero extension, emit a zero constant. This doesn't handle cases when + // sign extension is specified. + const MCConstantExpr *C = MCConstantExpr::create(0, OutStreamer->getContext()); + OutStreamer->emitValue(ME, DL.getTypeAllocSize(Op->getType())); + OutStreamer->emitValue(C, DL.getTypeAllocSize(Op->getType())); + } else if (DstAS == X86AS::PTR32_SPTR || DstAS == X86AS::PTR32_UPTR) { + // For trunc, just remove the addrspacecast. + AsmPrinter::emitGlobalConstant(DL, Op); + } else { + // Otherwise fallthrough to general case. + AsmPrinter::emitGlobalConstant(DL, CV); + } +} + /// PrintSymbolOperand - Print a raw symbol reference operand. This handles /// jump tables, constant pools, global address and external symbols, all of /// which print to a label with various suffixes for relocation types etc. diff --git a/llvm/test/CodeGen/X86/mixed-ptr-sizes-i686.ll b/llvm/test/CodeGen/X86/mixed-ptr-sizes-i686.ll --- a/llvm/test/CodeGen/X86/mixed-ptr-sizes-i686.ll +++ b/llvm/test/CodeGen/X86/mixed-ptr-sizes-i686.ll @@ -343,3 +343,17 @@ store i32 %i, i32 addrspace(272)* %s, align 8 ret void } + +; Test addrspacecast in static initializers. +@teststr = dso_local global [8 x i8] c"teststr\00", align 1 +@global64 = dso_local global i8 addrspace(272)* addrspacecast (i8* getelementptr inbounds ([8 x i8], [8 x i8]* @teststr, i32 0, i32 0) to i8 addrspace(272)*), align 8 + +define dso_local i8 addrspace(272)* @test_global_zext() { +; ALL-LABEL: test_global_zext: +; ALL: # %bb.0: # %entry +; ALL-NEXT: movl _global64, %eax +; ALL-NEXT: movl _global64+4, %edx +entry: + %0 = load i8 addrspace(272)*, i8 addrspace(272)** @global64, align 8 + ret i8 addrspace(272)* %0 +} diff --git a/llvm/test/CodeGen/X86/mixed-ptr-sizes.ll b/llvm/test/CodeGen/X86/mixed-ptr-sizes.ll --- a/llvm/test/CodeGen/X86/mixed-ptr-sizes.ll +++ b/llvm/test/CodeGen/X86/mixed-ptr-sizes.ll @@ -259,3 +259,17 @@ store i32 %i, i32 addrspace(272)* %s, align 8 ret void } + +; Test addrspacecast in static initializers. +@teststr = dso_local global [8 x i8] c"teststr\00", align 1 +@global32 = dso_local global i8 addrspace(270)* addrspacecast (i8* getelementptr inbounds ([8 x i8], [8 x i8]* @teststr, i32 0, i32 0) to i8 addrspace(270)*), align 8 + +define dso_local i8 addrspace(270)* @test_global_trunc() { +; ALL-LABEL: test_global_trunc: +; ALL: # %bb.0: # %entry +; ALL-NEXT: movl global32(%rip), %eax +; ALL-NEXT: retq +entry: + %0 = load i8 addrspace(270)*, i8 addrspace(270)** @global32, align 4 + ret i8 addrspace(270)* %0 +}