diff options
author | David Majnemer <david.majnemer@gmail.com> | 2014-01-15 09:16:42 +0000 |
---|---|---|
committer | David Majnemer <david.majnemer@gmail.com> | 2014-01-15 09:16:42 +0000 |
commit | dee105772c5b5662e1a046b1c102467c84a09d26 (patch) | |
tree | c1395726ad714912c52e1f8edbabaed8c863ac88 /llvm/lib/Target/X86/X86TargetObjectFile.cpp | |
parent | 888d52a6556eec27341ba635a64315dd08c269aa (diff) | |
download | bcm5719-llvm-dee105772c5b5662e1a046b1c102467c84a09d26.tar.gz bcm5719-llvm-dee105772c5b5662e1a046b1c102467c84a09d26.zip |
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
llvm-svn: 199312
Diffstat (limited to 'llvm/lib/Target/X86/X86TargetObjectFile.cpp')
-rw-r--r-- | llvm/lib/Target/X86/X86TargetObjectFile.cpp | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/llvm/lib/Target/X86/X86TargetObjectFile.cpp b/llvm/lib/Target/X86/X86TargetObjectFile.cpp index 709fc972560..bc1064e17f4 100644 --- a/llvm/lib/Target/X86/X86TargetObjectFile.cpp +++ b/llvm/lib/Target/X86/X86TargetObjectFile.cpp @@ -9,6 +9,7 @@ #include "X86TargetObjectFile.h" #include "llvm/IR/Mangler.h" +#include "llvm/IR/Operator.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCSectionELF.h" @@ -53,3 +54,54 @@ X86LinuxTargetObjectFile::getDebugThreadLocalSymbol( const MCSymbol *Sym) const { return MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_DTPOFF, getContext()); } + +const MCExpr * +X86WindowsTargetObjectFile::getExecutableRelativeSymbol(const ConstantExpr *CE, + Mangler *Mang) const { + // We are looking for the difference of two symbols, need a subtraction + // operation. + const SubOperator *Sub = dyn_cast<SubOperator>(CE); + if (!Sub) + return 0; + + // Symbols must first be numbers before we can subtract them, we need to see a + // ptrtoint on both subtraction operands. + const PtrToIntOperator *SubLHS = + dyn_cast<PtrToIntOperator>(Sub->getOperand(0)); + const PtrToIntOperator *SubRHS = + dyn_cast<PtrToIntOperator>(Sub->getOperand(1)); + if (!SubLHS || !SubRHS) + return 0; + + // Our symbols should exist in address space zero, cowardly no-op if + // otherwise. + if (SubLHS->getPointerAddressSpace() != 0 || + SubRHS->getPointerAddressSpace() != 0) + return 0; + + // Both ptrtoint instructions must wrap global variables: + // - Only global variables are eligible for image relative relocations. + // - The subtrahend refers to the special symbol __ImageBase, a global. + const GlobalVariable *GVLHS = + dyn_cast<GlobalVariable>(SubLHS->getPointerOperand()); + const GlobalVariable *GVRHS = + dyn_cast<GlobalVariable>(SubRHS->getPointerOperand()); + if (!GVLHS || !GVRHS) + return 0; + + // We expect __ImageBase to be a global variable without a section, externally + // defined. + // + // It should look something like this: @__ImageBase = external constant i8 + if (GVRHS->isThreadLocal() || GVRHS->getName() != "__ImageBase" || + !GVRHS->hasExternalLinkage() || GVRHS->hasInitializer() || + GVRHS->hasSection()) + return 0; + + // An image-relative, thread-local, symbol makes no sense. + if (GVLHS->isThreadLocal()) + return 0; + + return MCSymbolRefExpr::Create( + getSymbol(*Mang, GVLHS), MCSymbolRefExpr::VK_COFF_IMGREL32, getContext()); +} |