llvm.org GIT mirror llvm / f62176f
WinCOFF: Transform IR expressions featuring __ImageBase into image relative relocations MSVC on x64 requires that we create image relative symbol references to refer to RTTI data. Seeing as how there is no way to explicitly make reference to a given relocation type in LLVM IR, pattern match expressions of the form &foo - &__ImageBase. Differential Revision: http://llvm-reviews.chandlerc.com/D2523 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@199312 91177308-0d34-0410-b5e6-96231b3b80d8 David Majnemer 6 years ago
7 changed file(s) with 106 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
472472
473473 };
474474
475 class PtrToIntOperator
476 : public ConcreteOperator {
477 friend class PtrToInt;
478 friend class ConstantExpr;
479
480 public:
481 Value *getPointerOperand() {
482 return getOperand(0);
483 }
484 const Value *getPointerOperand() const {
485 return getOperand(0);
486 }
487 static unsigned getPointerOperandIndex() {
488 return 0U; // get index for modifying correct operand
489 }
490
491 /// getPointerOperandType - Method to return the pointer operand as a
492 /// PointerType.
493 Type *getPointerOperandType() const {
494 return getPointerOperand()->getType();
495 }
496
497 /// getPointerAddressSpace - Method to return the address space of the
498 /// pointer operand.
499 unsigned getPointerAddressSpace() const {
500 return cast(getPointerOperandType())->getAddressSpace();
501 }
502 };
503
504
475505 } // End llvm namespace
476506
477507 #endif
2828 class MCSymbol;
2929 class MCSymbolRefExpr;
3030 class MCStreamer;
31 class ConstantExpr;
3132 class GlobalValue;
3233 class TargetMachine;
3334
151152 /// emitting the address in debug info.
152153 virtual const MCExpr *getDebugThreadLocalSymbol(const MCSymbol *Sym) const;
153154
155 virtual const MCExpr *
156 getExecutableRelativeSymbol(const ConstantExpr *CE, Mangler *Mang) const {
157 return 0;
158 }
159
154160 protected:
155161 virtual const MCSection *
156162 SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind,
15111511 llvm_unreachable("Unknown constant value to lower!");
15121512 }
15131513
1514 if (const MCExpr *RelocExpr =
1515 AP.getObjFileLowering().getExecutableRelativeSymbol(CE, AP.Mang))
1516 return RelocExpr;
1517
15141518 switch (CE->getOpcode()) {
15151519 default:
15161520 // If the code isn't optimized, there may be outstanding folding
188188 return new X86LinuxTargetObjectFile();
189189 if (Subtarget->isTargetELF())
190190 return new TargetLoweringObjectFileELF();
191 if (Subtarget->isTargetWindows())
192 return new X86WindowsTargetObjectFile();
191193 if (Subtarget->isTargetCOFF())
192194 return new TargetLoweringObjectFileCOFF();
193195 llvm_unreachable("unknown subtarget type");
88
99 #include "X86TargetObjectFile.h"
1010 #include "llvm/IR/Mangler.h"
11 #include "llvm/IR/Operator.h"
1112 #include "llvm/MC/MCContext.h"
1213 #include "llvm/MC/MCExpr.h"
1314 #include "llvm/MC/MCSectionELF.h"
5253 const MCSymbol *Sym) const {
5354 return MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_DTPOFF, getContext());
5455 }
56
57 const MCExpr *
58 X86WindowsTargetObjectFile::getExecutableRelativeSymbol(const ConstantExpr *CE,
59 Mangler *Mang) const {
60 // We are looking for the difference of two symbols, need a subtraction
61 // operation.
62 const SubOperator *Sub = dyn_cast(CE);
63 if (!Sub)
64 return 0;
65
66 // Symbols must first be numbers before we can subtract them, we need to see a
67 // ptrtoint on both subtraction operands.
68 const PtrToIntOperator *SubLHS =
69 dyn_cast(Sub->getOperand(0));
70 const PtrToIntOperator *SubRHS =
71 dyn_cast(Sub->getOperand(1));
72 if (!SubLHS || !SubRHS)
73 return 0;
74
75 // Our symbols should exist in address space zero, cowardly no-op if
76 // otherwise.
77 if (SubLHS->getPointerAddressSpace() != 0 ||
78 SubRHS->getPointerAddressSpace() != 0)
79 return 0;
80
81 // Both ptrtoint instructions must wrap global variables:
82 // - Only global variables are eligible for image relative relocations.
83 // - The subtrahend refers to the special symbol __ImageBase, a global.
84 const GlobalVariable *GVLHS =
85 dyn_cast(SubLHS->getPointerOperand());
86 const GlobalVariable *GVRHS =
87 dyn_cast(SubRHS->getPointerOperand());
88 if (!GVLHS || !GVRHS)
89 return 0;
90
91 // We expect __ImageBase to be a global variable without a section, externally
92 // defined.
93 //
94 // It should look something like this: @__ImageBase = external constant i8
95 if (GVRHS->isThreadLocal() || GVRHS->getName() != "__ImageBase" ||
96 !GVRHS->hasExternalLinkage() || GVRHS->hasInitializer() ||
97 GVRHS->hasSection())
98 return 0;
99
100 // An image-relative, thread-local, symbol makes no sense.
101 if (GVLHS->isThreadLocal())
102 return 0;
103
104 return MCSymbolRefExpr::Create(
105 getSymbol(*Mang, GVLHS), MCSymbolRefExpr::VK_COFF_IMGREL32, getContext());
106 }
4040 virtual const MCExpr *getDebugThreadLocalSymbol(const MCSymbol *Sym) const;
4141 };
4242
43 /// \brief This implementation is used for Windows targets on x86 and x86-64.
44 class X86WindowsTargetObjectFile : public TargetLoweringObjectFileCOFF {
45 virtual const MCExpr *getExecutableRelativeSymbol(const ConstantExpr *CE,
46 Mangler *Mang) const;
47 };
48
4349 } // end namespace llvm
4450
4551 #endif
0 ; RUN: llc -mtriple=x86_64-pc-win32 %s -o - | FileCheck %s --check-prefix=X64
1
2 @__ImageBase = external global i8
3
4 ; X64: .quad "?x@@3HA"@IMGREL32
5 @"\01?x@@3HA" = global i64 sub nsw (i64 ptrtoint (i64* @"\01?x@@3HA" to i64), i64 ptrtoint (i8* @__ImageBase to i64)), align 8