[llvm] r199312 - WinCOFF: Transform IR expressions featuring __ImageBase into image relative relocations

David Majnemer david.majnemer at gmail.com
Wed Jan 15 01:16:45 PST 2014


Author: majnemer
Date: Wed Jan 15 03:16:42 2014
New Revision: 199312

URL: http://llvm.org/viewvc/llvm-project?rev=199312&view=rev
Log:
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

Added:
    llvm/trunk/test/MC/COFF/ir-to-imgrel.ll
Modified:
    llvm/trunk/include/llvm/IR/Operator.h
    llvm/trunk/include/llvm/Target/TargetLoweringObjectFile.h
    llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
    llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
    llvm/trunk/lib/Target/X86/X86TargetObjectFile.cpp
    llvm/trunk/lib/Target/X86/X86TargetObjectFile.h

Modified: llvm/trunk/include/llvm/IR/Operator.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Operator.h?rev=199312&r1=199311&r2=199312&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/Operator.h (original)
+++ llvm/trunk/include/llvm/IR/Operator.h Wed Jan 15 03:16:42 2014
@@ -473,6 +473,36 @@ public:
 
 };
 
+class PtrToIntOperator
+    : public ConcreteOperator<Operator, Instruction::PtrToInt> {
+  friend class PtrToInt;
+  friend class ConstantExpr;
+
+public:
+  Value *getPointerOperand() {
+    return getOperand(0);
+  }
+  const Value *getPointerOperand() const {
+    return getOperand(0);
+  }
+  static unsigned getPointerOperandIndex() {
+    return 0U;                      // get index for modifying correct operand
+  }
+
+  /// getPointerOperandType - Method to return the pointer operand as a
+  /// PointerType.
+  Type *getPointerOperandType() const {
+    return getPointerOperand()->getType();
+  }
+
+  /// getPointerAddressSpace - Method to return the address space of the
+  /// pointer operand.
+  unsigned getPointerAddressSpace() const {
+    return cast<PointerType>(getPointerOperandType())->getAddressSpace();
+  }
+};
+
+
 } // End llvm namespace
 
 #endif

Modified: llvm/trunk/include/llvm/Target/TargetLoweringObjectFile.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetLoweringObjectFile.h?rev=199312&r1=199311&r2=199312&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Target/TargetLoweringObjectFile.h (original)
+++ llvm/trunk/include/llvm/Target/TargetLoweringObjectFile.h Wed Jan 15 03:16:42 2014
@@ -29,6 +29,7 @@ namespace llvm {
   class MCSymbol;
   class MCSymbolRefExpr;
   class MCStreamer;
+  class ConstantExpr;
   class GlobalValue;
   class TargetMachine;
   
@@ -152,6 +153,11 @@ public:
   /// emitting the address in debug info.
   virtual const MCExpr *getDebugThreadLocalSymbol(const MCSymbol *Sym) const;
 
+  virtual const MCExpr *
+  getExecutableRelativeSymbol(const ConstantExpr *CE, Mangler *Mang) const {
+    return 0;
+  }
+
 protected:
   virtual const MCSection *
   SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind,

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp?rev=199312&r1=199311&r2=199312&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp Wed Jan 15 03:16:42 2014
@@ -1512,6 +1512,10 @@ static const MCExpr *lowerConstant(const
     llvm_unreachable("Unknown constant value to lower!");
   }
 
+  if (const MCExpr *RelocExpr =
+          AP.getObjFileLowering().getExecutableRelativeSymbol(CE, AP.Mang))
+    return RelocExpr;
+
   switch (CE->getOpcode()) {
   default:
     // If the code isn't optimized, there may be outstanding folding

Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=199312&r1=199311&r2=199312&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Wed Jan 15 03:16:42 2014
@@ -189,6 +189,8 @@ static TargetLoweringObjectFile *createT
     return new X86LinuxTargetObjectFile();
   if (Subtarget->isTargetELF())
     return new TargetLoweringObjectFileELF();
+  if (Subtarget->isTargetWindows())
+    return new X86WindowsTargetObjectFile();
   if (Subtarget->isTargetCOFF())
     return new TargetLoweringObjectFileCOFF();
   llvm_unreachable("unknown subtarget type");

Modified: llvm/trunk/lib/Target/X86/X86TargetObjectFile.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86TargetObjectFile.cpp?rev=199312&r1=199311&r2=199312&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86TargetObjectFile.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86TargetObjectFile.cpp Wed Jan 15 03:16:42 2014
@@ -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::getDebugThread
     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());
+}

Modified: llvm/trunk/lib/Target/X86/X86TargetObjectFile.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86TargetObjectFile.h?rev=199312&r1=199311&r2=199312&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86TargetObjectFile.h (original)
+++ llvm/trunk/lib/Target/X86/X86TargetObjectFile.h Wed Jan 15 03:16:42 2014
@@ -41,6 +41,12 @@ namespace llvm {
     virtual const MCExpr *getDebugThreadLocalSymbol(const MCSymbol *Sym) const;
   };
 
+  /// \brief This implementation is used for Windows targets on x86 and x86-64.
+  class X86WindowsTargetObjectFile : public TargetLoweringObjectFileCOFF {
+    virtual const MCExpr *getExecutableRelativeSymbol(const ConstantExpr *CE,
+                                                      Mangler *Mang) const;
+  };
+
 } // end namespace llvm
 
 #endif

Added: llvm/trunk/test/MC/COFF/ir-to-imgrel.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/COFF/ir-to-imgrel.ll?rev=199312&view=auto
==============================================================================
--- llvm/trunk/test/MC/COFF/ir-to-imgrel.ll (added)
+++ llvm/trunk/test/MC/COFF/ir-to-imgrel.ll Wed Jan 15 03:16:42 2014
@@ -0,0 +1,6 @@
+; RUN: llc -mtriple=x86_64-pc-win32 %s -o - | FileCheck %s --check-prefix=X64
+
+ at __ImageBase = external global i8
+
+; X64: .quad   "?x@@3HA"@IMGREL32
+@"\01?x@@3HA" = global i64 sub nsw (i64 ptrtoint (i64* @"\01?x@@3HA" to i64), i64 ptrtoint (i8* @__ImageBase to i64)), align 8





More information about the llvm-commits mailing list