-no-implicit-float means explicit fp operations are legal.
[oota-llvm.git] / lib / Target / X86 / X86CodeEmitter.cpp
index e5bef574e934543303e0d8a03f279083ff9f9b6e..bbe063b4f821efb2b4b6ce8b150907c122e5c7e2 100644 (file)
@@ -72,10 +72,10 @@ namespace {
   private:
     void emitPCRelativeBlockAddress(MachineBasicBlock *MBB);
     void emitGlobalAddress(GlobalValue *GV, unsigned Reloc,
-                           int Disp = 0, intptr_t PCAdj = 0,
-                           bool NeedStub = false, bool IsLazy = false);
+                           intptr_t Disp = 0, intptr_t PCAdj = 0,
+                           bool NeedStub = false, bool Indirect = false);
     void emitExternalSymbolAddress(const char *ES, unsigned Reloc);
-    void emitConstPoolAddress(unsigned CPI, unsigned Reloc, int Disp = 0,
+    void emitConstPoolAddress(unsigned CPI, unsigned Reloc, intptr_t Disp = 0,
                               intptr_t PCAdj = 0);
     void emitJumpTableAddress(unsigned JTI, unsigned Reloc,
                               intptr_t PCAdj = 0);
@@ -94,7 +94,7 @@ namespace {
 
     unsigned getX86RegNum(unsigned RegNo) const;
 
-    bool gvNeedsLazyPtr(const GlobalValue *GV);
+    bool gvNeedsNonLazyPtr(const GlobalValue *GV);
   };
   char Emitter::ID = 0;
 }
@@ -152,23 +152,26 @@ void Emitter::emitPCRelativeBlockAddress(MachineBasicBlock *MBB) {
 /// this is part of a "take the address of a global" instruction.
 ///
 void Emitter::emitGlobalAddress(GlobalValue *GV, unsigned Reloc,
-                                int Disp /* = 0 */, intptr_t PCAdj /* = 0 */,
+                                intptr_t Disp /* = 0 */,
+                                intptr_t PCAdj /* = 0 */,
                                 bool NeedStub /* = false */,
-                                bool isLazy /* = false */) {
+                                bool Indirect /* = false */) {
   intptr_t RelocCST = 0;
   if (Reloc == X86::reloc_picrel_word)
     RelocCST = PICBaseOffset;
   else if (Reloc == X86::reloc_pcrel_word)
     RelocCST = PCAdj;
-  MachineRelocation MR = isLazy 
-    ? MachineRelocation::getGVLazyPtr(MCE.getCurrentPCOffset(), Reloc,
-                                      GV, RelocCST, NeedStub)
+  MachineRelocation MR = Indirect
+    ? MachineRelocation::getIndirectSymbol(MCE.getCurrentPCOffset(), Reloc,
+                                           GV, RelocCST, NeedStub)
     : MachineRelocation::getGV(MCE.getCurrentPCOffset(), Reloc,
                                GV, RelocCST, NeedStub);
   MCE.addRelocation(MR);
+  // The relocated value will be added to the displacement
   if (Reloc == X86::reloc_absolute_dword)
-    MCE.emitWordLE(0);
-  MCE.emitWordLE(Disp); // The relocated value will be added to the displacement
+    MCE.emitDWordLE(Disp);
+  else
+    MCE.emitWordLE((int32_t)Disp);
 }
 
 /// emitExternalSymbolAddress - Arrange for the address of an external symbol to
@@ -179,15 +182,16 @@ void Emitter::emitExternalSymbolAddress(const char *ES, unsigned Reloc) {
   MCE.addRelocation(MachineRelocation::getExtSym(MCE.getCurrentPCOffset(),
                                                  Reloc, ES, RelocCST));
   if (Reloc == X86::reloc_absolute_dword)
+    MCE.emitDWordLE(0);
+  else
     MCE.emitWordLE(0);
-  MCE.emitWordLE(0);
 }
 
 /// emitConstPoolAddress - Arrange for the address of an constant pool
 /// to be emitted to the current location in the function, and allow it to be PC
 /// relative.
 void Emitter::emitConstPoolAddress(unsigned CPI, unsigned Reloc,
-                                   int Disp /* = 0 */,
+                                   intptr_t Disp /* = 0 */,
                                    intptr_t PCAdj /* = 0 */) {
   intptr_t RelocCST = 0;
   if (Reloc == X86::reloc_picrel_word)
@@ -196,9 +200,11 @@ void Emitter::emitConstPoolAddress(unsigned CPI, unsigned Reloc,
     RelocCST = PCAdj;
   MCE.addRelocation(MachineRelocation::getConstPool(MCE.getCurrentPCOffset(),
                                                     Reloc, CPI, RelocCST));
+  // The relocated value will be added to the displacement
   if (Reloc == X86::reloc_absolute_dword)
-    MCE.emitWordLE(0);
-  MCE.emitWordLE(Disp); // The relocated value will be added to the displacement
+    MCE.emitDWordLE(Disp);
+  else
+    MCE.emitWordLE((int32_t)Disp);
 }
 
 /// emitJumpTableAddress - Arrange for the address of a jump table to
@@ -213,9 +219,11 @@ void Emitter::emitJumpTableAddress(unsigned JTI, unsigned Reloc,
     RelocCST = PCAdj;
   MCE.addRelocation(MachineRelocation::getJumpTable(MCE.getCurrentPCOffset(),
                                                     Reloc, JTI, RelocCST));
+  // The relocated value will be added to the displacement
   if (Reloc == X86::reloc_absolute_dword)
+    MCE.emitDWordLE(0);
+  else
     MCE.emitWordLE(0);
-  MCE.emitWordLE(0); // The relocated value will be added to the displacement
 }
 
 unsigned Emitter::getX86RegNum(unsigned RegNo) const {
@@ -255,8 +263,8 @@ static bool isDisp8(int Value) {
   return Value == (signed char)Value;
 }
 
-bool Emitter::gvNeedsLazyPtr(const GlobalValue *GV) {
-  // For Darwin, simulate the linktime GOT by using the same lazy-pointer
+bool Emitter::gvNeedsNonLazyPtr(const GlobalValue *GV) {
+  // For Darwin, simulate the linktime GOT by using the same non-lazy-pointer
   // mechanism as 32-bit mode.
   return (!Is64BitMode || TM.getSubtarget<X86Subtarget>().isTargetDarwin()) &&
     TM.getSubtarget<X86Subtarget>().GVRequiresExtraLoad(GV, TM, false);
@@ -281,9 +289,9 @@ void Emitter::emitDisplacementField(const MachineOperand *RelocOp,
     unsigned rt = Is64BitMode ? X86::reloc_pcrel_word
       : (IsPIC ? X86::reloc_picrel_word : X86::reloc_absolute_word);
     bool NeedStub = isa<Function>(RelocOp->getGlobal());
-    bool isLazy = gvNeedsLazyPtr(RelocOp->getGlobal());
+    bool Indirect = gvNeedsNonLazyPtr(RelocOp->getGlobal());
     emitGlobalAddress(RelocOp->getGlobal(), rt, RelocOp->getOffset(),
-                      PCAdj, NeedStub, isLazy);
+                      PCAdj, NeedStub, Indirect);
   } else if (RelocOp->isCPI()) {
     unsigned rt = Is64BitMode ? X86::reloc_pcrel_word : X86::reloc_picrel_word;
     emitConstPoolAddress(RelocOp->getIndex(), rt,
@@ -330,7 +338,7 @@ void Emitter::emitMemModRMByte(const MachineInstr &MI,
   unsigned BaseReg = Base.getReg();
 
   // Is a SIB byte needed?
-  if (IndexReg.getReg() == 0 &&
+  if ((!Is64BitMode || DispForReloc) && IndexReg.getReg() == 0 &&
       (BaseReg == 0 || getX86RegNum(BaseReg) != N86::ESP)) {
     if (BaseReg == 0) {  // Just a displacement?
       // Emit special case [disp32] encoding
@@ -387,8 +395,12 @@ void Emitter::emitMemModRMByte(const MachineInstr &MI,
     if (BaseReg == 0) {
       // Handle the SIB byte for the case where there is no base.  The
       // displacement has already been output.
-      assert(IndexReg.getReg() && "Index register must be specified!");
-      emitSIBByte(SS, getX86RegNum(IndexReg.getReg()), 5);
+      unsigned IndexRegNo;
+      if (IndexReg.getReg())
+        IndexRegNo = getX86RegNum(IndexReg.getReg());
+      else
+        IndexRegNo = 4;   // For example [ESP+1*<noreg>+4]
+      emitSIBByte(SS, IndexRegNo, 5);
     } else {
       unsigned BaseRegNo = getX86RegNum(BaseReg);
       unsigned IndexRegNo;
@@ -504,10 +516,12 @@ void Emitter::emitInstruction(const MachineInstr &MI,
       assert(0 && "psuedo instructions should be removed before code emission");
       break;
     case TargetInstrInfo::INLINEASM: {
-      const char* Value = MI.getOperand(0).getSymbolName();
-      /* We allow inline assembler nodes with empty bodies - they can
-         implicitly define registers, which is ok for JIT. */
-      assert((Value[0] == 0) && "JIT does not support inline asm!\n");
+      // We allow inline assembler nodes with empty bodies - they can
+      // implicitly define registers, which is ok for JIT.
+      if (MI.getOperand(0).getSymbolName()[0]) {
+        assert(0 && "JIT does not support inline asm!\n");
+        abort();
+      }
       break;
     }
     case TargetInstrInfo::DBG_LABEL:
@@ -519,12 +533,29 @@ void Emitter::emitInstruction(const MachineInstr &MI,
     case X86::DWARF_LOC:
     case X86::FP_REG_KILL:
       break;
+    case X86::TLS_tp: {
+      MCE.emitByte(BaseOpcode);
+      unsigned RegOpcodeField = getX86RegNum(MI.getOperand(0).getReg());
+      MCE.emitByte(ModRMByte(0, RegOpcodeField, 5));
+      emitConstant(0, 4);
+      break;
+    }
+    case X86::TLS_gs_ri: {
+      MCE.emitByte(BaseOpcode);
+      unsigned RegOpcodeField = getX86RegNum(MI.getOperand(0).getReg());
+      MCE.emitByte(ModRMByte(0, RegOpcodeField, 5));
+      GlobalValue* GV = MI.getOperand(1).getGlobal();
+      unsigned rt = Is64BitMode ? X86::reloc_pcrel_word
+        : (IsPIC ? X86::reloc_picrel_word : X86::reloc_absolute_word);
+      emitGlobalAddress(GV, rt);
+      break;
+    }
     case X86::MOVPC32r: {
       // This emits the "call" portion of this pseudo instruction.
       MCE.emitByte(BaseOpcode);
       emitConstant(0, X86InstrInfo::sizeOfImm(Desc));
       // Remember PIC base.
-      PICBaseOffset = MCE.getCurrentPCOffset();
+      PICBaseOffset = (intptr_t) MCE.getCurrentPCOffset();
       X86JITInfo *JTI = TM.getJITInfo();
       JTI->setPICBase(MCE.getCurrentPCValue());
       break;
@@ -554,11 +585,17 @@ void Emitter::emitInstruction(const MachineInstr &MI,
                TM.getSubtarget<X86Subtarget>().isTargetDarwin())) ||
           Opcode == X86::TAILJMPd;
         emitGlobalAddress(MO.getGlobal(), X86::reloc_pcrel_word,
-                          0, 0, NeedStub);
+                          MO.getOffset(), 0, NeedStub);
       } else if (MO.isSymbol()) {
         emitExternalSymbolAddress(MO.getSymbolName(), X86::reloc_pcrel_word);
       } else if (MO.isImm()) {
-        emitConstant(MO.getImm(), X86InstrInfo::sizeOfImm(Desc));
+        if (Opcode == X86::CALLpcrel32 || Opcode == X86::CALL64pcrel32) {
+          // Fix up immediate operand for pc relative calls.
+          intptr_t Imm = (intptr_t)MO.getImm();
+          Imm = Imm - MCE.getCurrentPCValue() - 4;
+          emitConstant(Imm, X86InstrInfo::sizeOfImm(Desc));
+        } else
+          emitConstant(MO.getImm(), X86InstrInfo::sizeOfImm(Desc));
       } else {
         assert(0 && "Unknown RawFrm operand!");
       }
@@ -581,9 +618,9 @@ void Emitter::emitInstruction(const MachineInstr &MI,
           rt = X86::reloc_absolute_dword;  // FIXME: add X86II flag?
         if (MO1.isGlobal()) {
           bool NeedStub = isa<Function>(MO1.getGlobal());
-          bool isLazy = gvNeedsLazyPtr(MO1.getGlobal());
+          bool Indirect = gvNeedsNonLazyPtr(MO1.getGlobal());
           emitGlobalAddress(MO1.getGlobal(), rt, MO1.getOffset(), 0,
-                            NeedStub, isLazy);
+                            NeedStub, Indirect);
         } else if (MO1.isSymbol())
           emitExternalSymbolAddress(MO1.getSymbolName(), rt);
         else if (MO1.isCPI())
@@ -659,9 +696,9 @@ void Emitter::emitInstruction(const MachineInstr &MI,
           rt = X86::reloc_absolute_word;  // FIXME: add X86II flag?
         if (MO1.isGlobal()) {
           bool NeedStub = isa<Function>(MO1.getGlobal());
-          bool isLazy = gvNeedsLazyPtr(MO1.getGlobal());
+          bool Indirect = gvNeedsNonLazyPtr(MO1.getGlobal());
           emitGlobalAddress(MO1.getGlobal(), rt, MO1.getOffset(), 0,
-                            NeedStub, isLazy);
+                            NeedStub, Indirect);
         } else if (MO1.isSymbol())
           emitExternalSymbolAddress(MO1.getSymbolName(), rt);
         else if (MO1.isCPI())
@@ -697,9 +734,9 @@ void Emitter::emitInstruction(const MachineInstr &MI,
           rt = X86::reloc_absolute_word;  // FIXME: add X86II flag?
         if (MO.isGlobal()) {
           bool NeedStub = isa<Function>(MO.getGlobal());
-          bool isLazy = gvNeedsLazyPtr(MO.getGlobal());
+          bool Indirect = gvNeedsNonLazyPtr(MO.getGlobal());
           emitGlobalAddress(MO.getGlobal(), rt, MO.getOffset(), 0,
-                            NeedStub, isLazy);
+                            NeedStub, Indirect);
         } else if (MO.isSymbol())
           emitExternalSymbolAddress(MO.getSymbolName(), rt);
         else if (MO.isCPI())