[llvm-commits] CVS: llvm/lib/Target/X86/X86ATTAsmPrinter.cpp X86ATTAsmPrinter.h X86ISelDAGToDAG.cpp X86ISelLowering.cpp X86ISelLowering.h X86InstrInfo.td X86IntelAsmPrinter.cpp X86IntelAsmPrinter.h X86Subtarget.cpp X86Subtarget.h

Evan Cheng evan.cheng at apple.com
Fri Feb 17 16:15:17 PST 2006



Changes in directory llvm/lib/Target/X86:

X86ATTAsmPrinter.cpp updated: 1.22 -> 1.23
X86ATTAsmPrinter.h updated: 1.6 -> 1.7
X86ISelDAGToDAG.cpp updated: 1.49 -> 1.50
X86ISelLowering.cpp updated: 1.88 -> 1.89
X86ISelLowering.h updated: 1.27 -> 1.28
X86InstrInfo.td updated: 1.237 -> 1.238
X86IntelAsmPrinter.cpp updated: 1.16 -> 1.17
X86IntelAsmPrinter.h updated: 1.7 -> 1.8
X86Subtarget.cpp updated: 1.25 -> 1.26
X86Subtarget.h updated: 1.11 -> 1.12
---
Log message:

x86 / Darwin PIC support.


---
Diffs of the changes:  (+143 -36)

 X86ATTAsmPrinter.cpp   |   23 +++++++++++++----------
 X86ATTAsmPrinter.h     |    1 +
 X86ISelDAGToDAG.cpp    |   39 +++++++++++++++++++++++++++++++++++++++
 X86ISelLowering.cpp    |   40 ++++++++++++++++++++++++++++++++--------
 X86ISelLowering.h      |    4 ++++
 X86InstrInfo.td        |    7 +++++++
 X86IntelAsmPrinter.cpp |   47 +++++++++++++++++++++++++++++++++++++++++++----
 X86IntelAsmPrinter.h   |    1 +
 X86Subtarget.cpp       |    5 +----
 X86Subtarget.h         |   12 ++----------
 10 files changed, 143 insertions(+), 36 deletions(-)


Index: llvm/lib/Target/X86/X86ATTAsmPrinter.cpp
diff -u llvm/lib/Target/X86/X86ATTAsmPrinter.cpp:1.22 llvm/lib/Target/X86/X86ATTAsmPrinter.cpp:1.23
--- llvm/lib/Target/X86/X86ATTAsmPrinter.cpp:1.22	Tue Feb  7 02:38:37 2006
+++ llvm/lib/Target/X86/X86ATTAsmPrinter.cpp	Fri Feb 17 18:15:05 2006
@@ -18,6 +18,7 @@
 #include "X86TargetMachine.h"
 #include "llvm/Module.h"
 #include "llvm/Support/Mangler.h"
+#include "llvm/Target/TargetOptions.h"
 #include <iostream>
 using namespace llvm;
 using namespace x86;
@@ -116,9 +117,9 @@
   case MachineOperand::MO_GlobalAddress: {
     bool isCallOp = Modifier && !strcmp(Modifier, "call");
     bool isMemOp  = Modifier && !strcmp(Modifier, "mem");
+    if (!isMemOp && !isCallOp) O << '$';
     // Darwin block shameless ripped from PPCAsmPrinter.cpp
     if (forDarwin) {
-      if (!isMemOp && !isCallOp) O << '$';
       GlobalValue *GV = MO.getGlobal();
       std::string Name = Mang->getValueName(GV);
       // Link-once, External, or Weakly-linked global variables need
@@ -132,19 +133,14 @@
         } else {
           GVStubs.insert(Name);
           O << "L" << Name << "$non_lazy_ptr";
+          if (PICEnabled)
+            O << "-\"L" << getFunctionNumber() << "$pb\"";
         }
       } else {
         O << Mang->getValueName(GV);
       }
-      int Offset = MO.getOffset();
-      if (Offset > 0)
-        O << "+" << Offset;
-      else if (Offset < 0)
-        O << Offset;
-      return;
-    }
-    if (!isMemOp && !isCallOp) O << '$';
-    O << Mang->getValueName(MO.getGlobal());
+    } else
+      O << Mang->getValueName(MO.getGlobal());
     int Offset = MO.getOffset();
     if (Offset > 0)
       O << "+" << Offset;
@@ -202,6 +198,8 @@
   } else if (BaseReg.isConstantPoolIndex()) {
     O << PrivateGlobalPrefix << "CPI" << getFunctionNumber() << "_"
       << BaseReg.getConstantPoolIndex();
+    if (forDarwin && PICEnabled)
+      O << "-\"L" << getFunctionNumber() << "$pb\"";
     if (DispSpec.getImmedValue())
       O << "+" << DispSpec.getImmedValue();
     if (IndexReg.getReg()) {
@@ -238,6 +236,11 @@
   }
 }
 
+void X86ATTAsmPrinter::printPICLabel(const MachineInstr *MI, unsigned Op) {
+  O << "\"L" << getFunctionNumber() << "$pb\"\n";
+  O << "\"L" << getFunctionNumber() << "$pb\":";
+}
+
 /// printMachineInstruction -- Print out a single X86 LLVM instruction
 /// MI in Intel syntax to the current output stream.
 ///


Index: llvm/lib/Target/X86/X86ATTAsmPrinter.h
diff -u llvm/lib/Target/X86/X86ATTAsmPrinter.h:1.6 llvm/lib/Target/X86/X86ATTAsmPrinter.h:1.7
--- llvm/lib/Target/X86/X86ATTAsmPrinter.h:1.6	Mon Feb  6 17:41:19 2006
+++ llvm/lib/Target/X86/X86ATTAsmPrinter.h	Fri Feb 17 18:15:05 2006
@@ -62,6 +62,7 @@
   void printMachineInstruction(const MachineInstr *MI);
   void printSSECC(const MachineInstr *MI, unsigned Op);
   void printMemReference(const MachineInstr *MI, unsigned Op);
+  void printPICLabel(const MachineInstr *MI, unsigned Op);
   bool runOnMachineFunction(MachineFunction &F);
 };
 


Index: llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
diff -u llvm/lib/Target/X86/X86ISelDAGToDAG.cpp:1.49 llvm/lib/Target/X86/X86ISelDAGToDAG.cpp:1.50
--- llvm/lib/Target/X86/X86ISelDAGToDAG.cpp:1.49	Fri Feb 10 20:05:36 2006
+++ llvm/lib/Target/X86/X86ISelDAGToDAG.cpp	Fri Feb 17 18:15:05 2006
@@ -85,12 +85,20 @@
     /// Subtarget - Keep a pointer to the X86Subtarget around so that we can
     /// make the right decision when generating code for different targets.
     const X86Subtarget *Subtarget;
+
+    unsigned GlobalBaseReg;
   public:
     X86DAGToDAGISel(TargetMachine &TM)
       : SelectionDAGISel(X86Lowering), X86Lowering(TM) {
       Subtarget = &TM.getSubtarget<X86Subtarget>();
     }
 
+    virtual bool runOnFunction(Function &Fn) {
+      // Make sure we re-emit a set of the global base reg if necessary
+      GlobalBaseReg = 0;
+      return SelectionDAGISel::runOnFunction(Fn);
+    }
+   
     virtual const char *getPassName() const {
       return "X86 DAG->DAG Instruction Selection";
     }
@@ -145,6 +153,10 @@
       return CurDAG->getTargetConstant(Imm, MVT::i32);
     }
 
+    /// getGlobalBaseReg - insert code into the entry mbb to materialize the PIC
+    /// base register.  Return the virtual register that holds this value.
+    SDOperand getGlobalBaseReg();
+
 #ifndef NDEBUG
     unsigned Indent;
 #endif
@@ -283,6 +295,7 @@
     break;
 
   case ISD::ConstantPool:
+  case ISD::TargetConstantPool:
     if (AM.BaseType == X86ISelAddressMode::RegBase && AM.Base.Reg.Val == 0) {
       if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(N)) {
         AM.BaseType = X86ISelAddressMode::ConstantPoolBase;
@@ -377,6 +390,10 @@
 
   // Is the base register already occupied?
   if (AM.BaseType != X86ISelAddressMode::RegBase || AM.Base.Reg.Val) {
+    // TargetConstantPool cannot be anything but the base.
+    if (N.getOpcode() == ISD::TargetConstantPool)
+      return true;
+
     // If so, check to see if the scale index register is set.
     if (AM.IndexReg.Val == 0) {
       AM.IndexReg = N;
@@ -478,6 +495,24 @@
   return false;
 }
 
+/// getGlobalBaseReg - Output the instructions required to put the
+/// base address to use for accessing globals into a register.
+///
+SDOperand X86DAGToDAGISel::getGlobalBaseReg() {
+  if (!GlobalBaseReg) {
+    // Insert the set of GlobalBaseReg into the first MBB of the function
+    MachineBasicBlock &FirstMBB = BB->getParent()->front();
+    MachineBasicBlock::iterator MBBI = FirstMBB.begin();
+    SSARegMap *RegMap = BB->getParent()->getSSARegMap();
+    // FIXME: when we get to LP64, we will need to create the appropriate
+    // type of register here.
+    GlobalBaseReg = RegMap->createVirtualRegister(X86::R32RegisterClass);
+    BuildMI(FirstMBB, MBBI, X86::MovePCtoStack, 0);
+    BuildMI(FirstMBB, MBBI, X86::POP32r, 1, GlobalBaseReg);
+  }
+  return CurDAG->getRegister(GlobalBaseReg, MVT::i32);
+}
+
 void X86DAGToDAGISel::Select(SDOperand &Result, SDOperand N) {
   SDNode *Node = N.Val;
   MVT::ValueType NVT = Node->getValueType(0);
@@ -603,6 +638,10 @@
 #endif
       return;
     }
+      
+    case X86ISD::GlobalBaseReg: 
+      Result = getGlobalBaseReg();
+      return;
 
     case ISD::SDIV:
     case ISD::UDIV:


Index: llvm/lib/Target/X86/X86ISelLowering.cpp
diff -u llvm/lib/Target/X86/X86ISelLowering.cpp:1.88 llvm/lib/Target/X86/X86ISelLowering.cpp:1.89
--- llvm/lib/Target/X86/X86ISelLowering.cpp:1.88	Fri Feb 17 01:09:27 2006
+++ llvm/lib/Target/X86/X86ISelLowering.cpp	Fri Feb 17 18:15:05 2006
@@ -162,6 +162,7 @@
   // X86 ret instruction may pop stack.
   setOperationAction(ISD::RET             , MVT::Other, Custom);
   // Darwin ABI issue.
+  setOperationAction(ISD::ConstantPool    , MVT::i32  , Custom);
   setOperationAction(ISD::GlobalAddress   , MVT::i32  , Custom);
   // 64-bit addm sub, shl, sra, srl (iff 32-bit x86)
   setOperationAction(ISD::SHL_PARTS       , MVT::i32  , Custom);
@@ -1788,21 +1789,43 @@
     return DAG.getNode(X86ISD::REP_MOVS, MVT::Other, Chain,
                        DAG.getValueType(AVT), InFlag);
   }
+  case ISD::ConstantPool: {
+    ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op);
+    SDOperand Result =
+      DAG.getTargetConstantPool(CP->get(), getPointerTy(), CP->getAlignment());
+    // Only lower ConstantPool on Darwin.
+    if (getTargetMachine().
+        getSubtarget<X86Subtarget>().isTargetDarwin()) {
+      // With PIC, the address is actually $g + Offset.
+      if (PICEnabled)
+        Result = DAG.getNode(ISD::ADD, getPointerTy(),
+                DAG.getNode(X86ISD::GlobalBaseReg, getPointerTy()), Result);    
+    }
+
+    return Result;
+  }
   case ISD::GlobalAddress: {
     SDOperand Result;
-    GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
-    // For Darwin, external and weak symbols are indirect, so we want to load
-    // the value at address GV, not the value of GV itself.  This means that
-    // the GlobalAddress must be in the base or index register of the address,
-    // not the GV offset field.
+    // Only lower GlobalAddress on Darwin.
     if (getTargetMachine().
-        getSubtarget<X86Subtarget>().getIndirectExternAndWeakGlobals()) {
+        getSubtarget<X86Subtarget>().isTargetDarwin()) {
+      GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
+      SDOperand Addr = DAG.getTargetGlobalAddress(GV, getPointerTy());
+      // With PIC, the address is actually $g + Offset.
+      if (PICEnabled)
+        Addr = DAG.getNode(ISD::ADD, getPointerTy(),
+                      DAG.getNode(X86ISD::GlobalBaseReg, getPointerTy()), Addr);
+
+      // For Darwin, external and weak symbols are indirect, so we want to load
+      // the value at address GV, not the value of GV itself.  This means that
+      // the GlobalAddress must be in the base or index register of the address,
+      // not the GV offset field.
       if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage() ||
           (GV->isExternal() && !GV->hasNotBeenReadFromBytecode()))
         Result = DAG.getLoad(MVT::i32, DAG.getEntryNode(),
-                             DAG.getTargetGlobalAddress(GV, getPointerTy()),
-                             DAG.getSrcValue(NULL));
+                             Addr, DAG.getSrcValue(NULL));
     }
+
     return Result;
   }
   case ISD::VASTART: {
@@ -1913,6 +1936,7 @@
   case X86ISD::REP_STOS:           return "X86ISD::RET_STOS";
   case X86ISD::REP_MOVS:           return "X86ISD::RET_MOVS";
   case X86ISD::LOAD_PACK:          return "X86ISD::LOAD_PACK";
+  case X86ISD::GlobalBaseReg:      return "X86ISD::GlobalBaseReg";
   }
 }
 


Index: llvm/lib/Target/X86/X86ISelLowering.h
diff -u llvm/lib/Target/X86/X86ISelLowering.h:1.27 llvm/lib/Target/X86/X86ISelLowering.h:1.28
--- llvm/lib/Target/X86/X86ISelLowering.h:1.27	Thu Feb 16 23:43:56 2006
+++ llvm/lib/Target/X86/X86ISelLowering.h	Fri Feb 17 18:15:05 2006
@@ -137,6 +137,10 @@
       /// LOAD_PACK Load a 128-bit packed float / double value. It has the same
       /// operands as a normal load.
       LOAD_PACK,
+
+      /// GlobalBaseReg - On Darwin, this node represents the result of the popl
+      /// at function entry, used for PIC code.
+      GlobalBaseReg,
     };
 
     // X86 specific condition code. These correspond to X86_*_COND in


Index: llvm/lib/Target/X86/X86InstrInfo.td
diff -u llvm/lib/Target/X86/X86InstrInfo.td:1.237 llvm/lib/Target/X86/X86InstrInfo.td:1.238
--- llvm/lib/Target/X86/X86InstrInfo.td:1.237	Thu Feb 16 23:43:56 2006
+++ llvm/lib/Target/X86/X86InstrInfo.td	Fri Feb 17 18:15:05 2006
@@ -144,6 +144,10 @@
   let PrintMethod = "printSSECC";
 }
 
+def piclabel: Operand<i32> {
+  let PrintMethod = "printPICLabel";
+}
+
 // A couple of more descriptive operand definitions.
 // 16-bits but only 8 bits are significant.
 def i16i8imm  : Operand<i16>;
@@ -537,6 +541,9 @@
 def POP32r   : I<0x58, AddRegFrm,
                  (ops R32:$reg), "pop{l} $reg", []>, Imp<[ESP],[ESP]>;
 
+def MovePCtoStack : I<0, Pseudo, (ops piclabel:$label),
+                      "call $label", []>;
+
 let isTwoAddress = 1 in                               // R32 = bswap R32
   def BSWAP32r : I<0xC8, AddRegFrm,
                    (ops R32:$dst, R32:$src),


Index: llvm/lib/Target/X86/X86IntelAsmPrinter.cpp
diff -u llvm/lib/Target/X86/X86IntelAsmPrinter.cpp:1.16 llvm/lib/Target/X86/X86IntelAsmPrinter.cpp:1.17
--- llvm/lib/Target/X86/X86IntelAsmPrinter.cpp:1.16	Tue Feb  7 02:38:37 2006
+++ llvm/lib/Target/X86/X86IntelAsmPrinter.cpp	Fri Feb 17 18:15:05 2006
@@ -18,6 +18,7 @@
 #include "llvm/Module.h"
 #include "llvm/Assembly/Writer.h"
 #include "llvm/Support/Mangler.h"
+#include "llvm/Target/TargetOptions.h"
 using namespace llvm;
 using namespace x86;
 
@@ -109,9 +110,32 @@
     abort ();
     return;
   case MachineOperand::MO_GlobalAddress: {
-    if (!Modifier || strcmp(Modifier, "call") || strcmp(Modifier, "mem"))
-      O << "OFFSET ";
-    O << Mang->getValueName(MO.getGlobal());
+    bool isCallOp = Modifier && !strcmp(Modifier, "call");
+    bool isMemOp  = Modifier && !strcmp(Modifier, "mem");
+    if (!isMemOp && !isCallOp) O << "OFFSET ";
+    if (forDarwin) {
+      GlobalValue *GV = MO.getGlobal();
+      std::string Name = Mang->getValueName(GV);
+      if (!isMemOp && !isCallOp) O << '$';
+      // Link-once, External, or Weakly-linked global variables need
+      // non-lazily-resolved stubs
+      if (GV->isExternal() || GV->hasWeakLinkage() ||
+          GV->hasLinkOnceLinkage()) {
+        // Dynamically-resolved functions need a stub for the function.
+        if (isCallOp && isa<Function>(GV) && cast<Function>(GV)->isExternal()) {
+          FnStubs.insert(Name);
+          O << "L" << Name << "$stub";
+        } else {
+          GVStubs.insert(Name);
+          O << "L" << Name << "$non_lazy_ptr";
+          if (PICEnabled)
+            O << "-\"L" << getFunctionNumber() << "$pb\"";
+        }
+      } else {
+        O << Mang->getValueName(GV);
+      }
+    } else
+      O << Mang->getValueName(MO.getGlobal());
     int Offset = MO.getOffset();
     if (Offset > 0)
       O << " + " << Offset;
@@ -119,9 +143,18 @@
       O << Offset;
     return;
   }
-  case MachineOperand::MO_ExternalSymbol:
+  case MachineOperand::MO_ExternalSymbol: {
+    bool isCallOp = Modifier && !strcmp(Modifier, "call");
+    bool isMemOp  = Modifier && !strcmp(Modifier, "mem");
+    if (isCallOp && forDarwin) {
+      std::string Name(GlobalPrefix); Name += MO.getSymbolName();
+      FnStubs.insert(Name);
+      O << "L" << Name << "$stub";
+      return;
+    }
     O << GlobalPrefix << MO.getSymbolName();
     return;
+  }
   default:
     O << "<unknown operand type>"; return;
   }
@@ -144,6 +177,8 @@
   } else if (BaseReg.isConstantPoolIndex()) {
     O << "[" << PrivateGlobalPrefix << "CPI" << getFunctionNumber() << "_"
       << BaseReg.getConstantPoolIndex();
+    if (forDarwin && PICEnabled)
+      O << "-\"L" << getFunctionNumber() << "$pb\"";
 
     if (IndexReg.getReg()) {
       O << " + ";
@@ -193,6 +228,10 @@
   O << "]";
 }
 
+void X86IntelAsmPrinter::printPICLabel(const MachineInstr *MI, unsigned Op) {
+  O << "\"L" << getFunctionNumber() << "$pb\"\n";
+  O << "\"L" << getFunctionNumber() << "$pb\":";
+}
 
 /// printMachineInstruction -- Print out a single X86 LLVM instruction
 /// MI in Intel syntax to the current output stream.


Index: llvm/lib/Target/X86/X86IntelAsmPrinter.h
diff -u llvm/lib/Target/X86/X86IntelAsmPrinter.h:1.7 llvm/lib/Target/X86/X86IntelAsmPrinter.h:1.8
--- llvm/lib/Target/X86/X86IntelAsmPrinter.h:1.7	Mon Feb  6 17:41:19 2006
+++ llvm/lib/Target/X86/X86IntelAsmPrinter.h	Fri Feb 17 18:15:05 2006
@@ -82,6 +82,7 @@
   void printOp(const MachineOperand &MO, const char *Modifier = 0);
   void printSSECC(const MachineInstr *MI, unsigned Op);
   void printMemReference(const MachineInstr *MI, unsigned Op);
+  void printPICLabel(const MachineInstr *MI, unsigned Op);
   bool runOnMachineFunction(MachineFunction &F);
   bool doInitialization(Module &M);
 };


Index: llvm/lib/Target/X86/X86Subtarget.cpp
diff -u llvm/lib/Target/X86/X86Subtarget.cpp:1.25 llvm/lib/Target/X86/X86Subtarget.cpp:1.26
--- llvm/lib/Target/X86/X86Subtarget.cpp:1.25	Wed Feb 15 18:21:07 2006
+++ llvm/lib/Target/X86/X86Subtarget.cpp	Fri Feb 17 18:15:05 2006
@@ -148,7 +148,6 @@
   stackAlignment = 8;
   // FIXME: this is a known good value for Yonah. Not sure about others.
   MinRepStrSizeThreshold = 128;
-  indirectExternAndWeakGlobals = false;
   X86SSELevel = NoMMXSSE;
   X863DNowLevel = NoThreeDNow;
   Is64Bit = false;
@@ -183,8 +182,6 @@
 #endif
   }
 
-  if (TargetType == isDarwin) {
+  if (TargetType == isDarwin)
     stackAlignment = 16;
-    indirectExternAndWeakGlobals = true;
-  }
 }


Index: llvm/lib/Target/X86/X86Subtarget.h
diff -u llvm/lib/Target/X86/X86Subtarget.h:1.11 llvm/lib/Target/X86/X86Subtarget.h:1.12
--- llvm/lib/Target/X86/X86Subtarget.h:1.11	Wed Feb 15 18:21:07 2006
+++ llvm/lib/Target/X86/X86Subtarget.h	Fri Feb 17 18:15:05 2006
@@ -47,9 +47,6 @@
   /// Min. memset / memcpy size that is turned into rep/movs, rep/stos ops.
   unsigned MinRepStrSizeThreshold;
 
-  /// Used by instruction selector
-  bool indirectExternAndWeakGlobals;
-
 public:
   enum {
     isELF, isCygwin, isDarwin, isWindows
@@ -71,13 +68,6 @@
   /// aligned.
   unsigned getMinRepStrSizeThreshold() const { return MinRepStrSizeThreshold; }
  
-  /// Returns true if the instruction selector should treat global values
-  /// referencing external or weak symbols as indirect rather than direct
-  /// references.
-  bool getIndirectExternAndWeakGlobals() const {
-    return indirectExternAndWeakGlobals;
-  }
-
   /// ParseSubtargetFeatures - Parses features string setting specified 
   /// subtarget options.  Definition of function is auto generated by tblgen.
   void ParseSubtargetFeatures(const std::string &FS, const std::string &CPU);
@@ -90,6 +80,8 @@
   bool hasSSE3() const { return X86SSELevel >= SSE3; }
   bool has3DNow() const { return X863DNowLevel >= ThreeDNow; }
   bool has3DNowA() const { return X863DNowLevel >= ThreeDNowA; }
+
+  bool isTargetDarwin() const { return TargetType == isDarwin; }
 };
 } // End llvm namespace
 






More information about the llvm-commits mailing list