[PATCH] WinCOFF: Transform IR expressions featuring __ImageBase into image relative relocations

David Majnemer david.majnemer at gmail.com
Mon Jan 13 23:39:39 PST 2014


    - Fix the sort order of forward declarations.

Hi nlewycky, nicholas, rafael, grosbach, rnk,

http://llvm-reviews.chandlerc.com/D2523

CHANGE SINCE LAST DIFF
  http://llvm-reviews.chandlerc.com/D2523?vs=6442&id=6443#toc

BRANCH
  IMAGEREL

ARCANIST PROJECT
  llvm

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

Index: include/llvm/IR/Operator.h
===================================================================
--- include/llvm/IR/Operator.h
+++ include/llvm/IR/Operator.h
@@ -473,6 +473,36 @@
 
 };
 
+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
Index: include/llvm/Target/TargetLoweringObjectFile.h
===================================================================
--- include/llvm/Target/TargetLoweringObjectFile.h
+++ include/llvm/Target/TargetLoweringObjectFile.h
@@ -29,6 +29,7 @@
   class MCSymbol;
   class MCSymbolRefExpr;
   class MCStreamer;
+  class ConstantExpr;
   class GlobalValue;
   class TargetMachine;
   
@@ -152,6 +153,11 @@
   /// 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,
Index: lib/CodeGen/AsmPrinter/AsmPrinter.cpp
===================================================================
--- lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -1514,6 +1514,10 @@
     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
Index: lib/Target/X86/X86ISelLowering.cpp
===================================================================
--- lib/Target/X86/X86ISelLowering.cpp
+++ lib/Target/X86/X86ISelLowering.cpp
@@ -189,6 +189,8 @@
     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");
Index: lib/Target/X86/X86TargetObjectFile.cpp
===================================================================
--- lib/Target/X86/X86TargetObjectFile.cpp
+++ 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 @@
     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());
+}
Index: lib/Target/X86/X86TargetObjectFile.h
===================================================================
--- lib/Target/X86/X86TargetObjectFile.h
+++ lib/Target/X86/X86TargetObjectFile.h
@@ -41,6 +41,12 @@
     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
Index: test/MC/COFF/ir-to-imgrel.ll
===================================================================
--- /dev/null
+++ test/MC/COFF/ir-to-imgrel.ll
@@ -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
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D2523.3.patch
Type: text/x-patch
Size: 6508 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20140113/3f03bebe/attachment.bin>


More information about the llvm-commits mailing list