summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/X86/X86TargetObjectFile.cpp
diff options
context:
space:
mode:
authorDavid Majnemer <david.majnemer@gmail.com>2014-01-15 09:16:42 +0000
committerDavid Majnemer <david.majnemer@gmail.com>2014-01-15 09:16:42 +0000
commitdee105772c5b5662e1a046b1c102467c84a09d26 (patch)
treec1395726ad714912c52e1f8edbabaed8c863ac88 /llvm/lib/Target/X86/X86TargetObjectFile.cpp
parent888d52a6556eec27341ba635a64315dd08c269aa (diff)
downloadbcm5719-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.cpp52
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());
+}
OpenPOWER on IntegriCloud