[PATCH v3 12/11] Fix incorrect encoding of relaxed instructions (PR18303)

David Woodhouse dwmw2 at infradead.org
Sat Dec 21 16:21:52 PST 2013


On Sat, 2013-12-21 at 20:22 +0000, David Woodhouse wrote:
> When .code64 or .code32 (or .code16) directives occur in an assembler
> file, all relaxed instructions will be encoded in whichever mode was
> active at the end of the file. Which is kind of broken.
> 
> http://llvm.org/bugs/show_bug.cgi?id=18303
> 
> Fix this by storing the active feature set *in* the MCInst, so that it
> can be correctly honoured when the instruction is re-encoded after
> relaxation.
> 
> Storing the feature set is optional; users which don't have a way to
> change the feature set will not need to bother as the SubtargetInfo will
> always have valid information and the code emitter will use that
> instead.

Jörg requested on IRC that I make the feature set mandatory for any
target that elects to use it, rather than falling back to using the
SubtargetInfo if no override has been set in the MCInst.

Here's what that would look like...

I could drop the isAvailableFeaturesSet() method on the MCInst now...
but it's useful for the assertions. I suspect they *will* be needed to
keep us honest, if we do it this way.

diff --git a/include/llvm/MC/MCInst.h b/include/llvm/MC/MCInst.h
index 4766815..de2c6f2 100644
--- a/include/llvm/MC/MCInst.h
+++ b/include/llvm/MC/MCInst.h
@@ -151,8 +151,11 @@ class MCInst {
   unsigned Opcode;
   SMLoc Loc;
   SmallVector<MCOperand, 8> Operands;
+  /// The current set of available features.
+  uint64_t AvailableFeatures;
+  bool AvailableFeaturesSet;
 public:
-  MCInst() : Opcode(0) {}
+  MCInst() : Opcode(0), AvailableFeatures(0), AvailableFeaturesSet(false) {}
 
   void setOpcode(unsigned Op) { Opcode = Op; }
   unsigned getOpcode() const { return Opcode; }
@@ -160,6 +163,13 @@ public:
   void setLoc(SMLoc loc) { Loc = loc; }
   SMLoc getLoc() const { return Loc; }
 
+  void setAvailableFeatures(uint64_t features) {
+    AvailableFeatures = features;
+    AvailableFeaturesSet = true;
+  }
+  bool isAvailableFeaturesSet() const { return AvailableFeaturesSet; }
+  uint64_t getAvailableFeatures() const { return AvailableFeatures; }
+
   const MCOperand &getOperand(unsigned i) const { return Operands[i]; }
   MCOperand &getOperand(unsigned i) { return Operands[i]; }
   unsigned getNumOperands() const { return Operands.size(); }
diff --git a/include/llvm/MC/MCInstBuilder.h b/include/llvm/MC/MCInstBuilder.h
index c5acb26..0959ee2 100644
--- a/include/llvm/MC/MCInstBuilder.h
+++ b/include/llvm/MC/MCInstBuilder.h
@@ -28,6 +28,11 @@ public:
     Inst.setOpcode(Opcode);
   }
 
+  MCInstBuilder(unsigned Opcode, uint64_t AvailableFeatures) {
+    Inst.setOpcode(Opcode);
+    Inst.setAvailableFeatures(AvailableFeatures);
+  }
+
   /// \brief Add a new register operand.
   MCInstBuilder &addReg(unsigned Reg) {
     Inst.addOperand(MCOperand::CreateReg(Reg));
diff --git a/lib/Target/X86/AsmParser/X86AsmParser.cpp b/lib/Target/X86/AsmParser/X86AsmParser.cpp
index 01746fa..2c9afbe 100644
--- a/lib/Target/X86/AsmParser/X86AsmParser.cpp
+++ b/lib/Target/X86/AsmParser/X86AsmParser.cpp
@@ -2422,6 +2422,7 @@ MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
     MCInst Inst;
     Inst.setOpcode(X86::WAIT);
     Inst.setLoc(IDLoc);
+    Inst.setAvailableFeatures(STI.getFeatureBits());
     if (!MatchingInlineAsm)
       Out.EmitInstruction(Inst);
 
@@ -2458,6 +2459,7 @@ MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
         ;
 
     Inst.setLoc(IDLoc);
+    Inst.setAvailableFeatures(STI.getFeatureBits());
     if (!MatchingInlineAsm)
       Out.EmitInstruction(Inst);
     Opcode = Inst.getOpcode();
@@ -2545,6 +2547,7 @@ MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
     (Match3 == Match_Success) + (Match4 == Match_Success);
   if (NumSuccessfulMatches == 1) {
     Inst.setLoc(IDLoc);
+    Inst.setAvailableFeatures(STI.getFeatureBits());
     if (!MatchingInlineAsm)
       Out.EmitInstruction(Inst);
     Opcode = Inst.getOpcode();
diff --git a/lib/Target/X86/Disassembler/X86Disassembler.cpp b/lib/Target/X86/Disassembler/X86Disassembler.cpp
index 903e36c..eb53ff3 100644
--- a/lib/Target/X86/Disassembler/X86Disassembler.cpp
+++ b/lib/Target/X86/Disassembler/X86Disassembler.cpp
@@ -70,6 +70,7 @@ extern Target TheX86_32Target, TheX86_64Target;
 
 static bool translateInstruction(MCInst &target,
                                 InternalInstruction &source,
+                                uint64_t AvailableFeatures,
                                 const MCDisassembler *Dis);
 
 X86GenericDisassembler::X86GenericDisassembler(const MCSubtargetInfo &STI,
@@ -141,7 +142,7 @@ X86GenericDisassembler::getInstruction(MCInst &instr,
   }
   else {
     size = internalInstr.length;
-    return (!translateInstruction(instr, internalInstr, this)) ?
+    return (!translateInstruction(instr, internalInstr, STI.getFeatureBits(), this)) ?
             Success : Fail;
   }
 }
@@ -676,6 +677,7 @@ static bool translateOperand(MCInst &mcInst, const OperandSpecifier &operand,
 /// @return             - false on success; true otherwise.
 static bool translateInstruction(MCInst &mcInst,
                                 InternalInstruction &insn,
+                                uint64_t AvailableFeatures,
                                 const MCDisassembler *Dis) {  
   if (!insn.spec) {
     debug("Instruction has no specification");
@@ -683,6 +685,7 @@ static bool translateInstruction(MCInst &mcInst,
   }
   
   mcInst.setOpcode(insn.instructionID);
+  mcInst.setAvailableFeatures(AvailableFeatures);
   // If when reading the prefix bytes we determined the overlapping 0xf2 or 0xf3
   // prefix bytes should be disassembled as xrelease and xacquire then set the
   // opcode to those instead of the rep and repne opcodes.
diff --git a/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp b/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
index 4392de2..8f9a976 100644
--- a/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
+++ b/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
@@ -42,20 +42,17 @@ public:
 
   ~X86MCCodeEmitter() {}
 
-  bool is64BitMode() const {
-    // FIXME: Can tablegen auto-generate this?
-    return (STI.getFeatureBits() & X86::Mode64Bit) != 0;
+  bool is64BitMode(const MCInst &MI) const {
+    return (MI.getAvailableFeatures() & X86::Mode64Bit) != 0;
   }
 
-  bool is32BitMode() const {
-    // FIXME: Can tablegen auto-generate this?
-    return (STI.getFeatureBits() & X86::Mode64Bit) == 0 &&
-           (STI.getFeatureBits() & X86::Mode16Bit) == 0;
+  bool is32BitMode(const MCInst &MI) const {
+    return (MI.getAvailableFeatures() & X86::Mode64Bit) == 0 &&
+           (MI.getAvailableFeatures() & X86::Mode16Bit) == 0;
   }
 
-  bool is16BitMode() const {
-    // FIXME: Can tablegen auto-generate this?
-    return (STI.getFeatureBits() & X86::Mode16Bit) != 0;
+  bool is16BitMode(const MCInst &MI) const {
+    return (MI.getAvailableFeatures() & X86::Mode16Bit) != 0;
   }
 
   /// Is16BitMemOperand - Return true if the specified instruction has
@@ -65,7 +62,7 @@ public:
     const MCOperand &IndexReg = MI.getOperand(Op+X86::AddrIndexReg);
     const MCOperand &Disp     = MI.getOperand(Op+X86::AddrDisp);
 
-    if (is16BitMode() && BaseReg.getReg() == 0 &&
+    if (is16BitMode(MI) && BaseReg.getReg() == 0 &&
         Disp.isImm() && Disp.getImm() < 0x10000)
       return true;
     if ((BaseReg.getReg() != 0 &&
@@ -387,7 +384,7 @@ void X86MCCodeEmitter::EmitMemModRMByte(const MCInst &MI, unsigned Op,
 
   // Handle %rip relative addressing.
   if (BaseReg == X86::RIP) {    // [disp32+RIP] in X86-64 mode
-    assert(is64BitMode() && "Rip-relative addressing requires 64-bit mode");
+    assert(is64BitMode(MI) && "Rip-relative addressing requires 64-bit mode");
     assert(IndexReg.getReg() == 0 && "Invalid rip-relative address");
     EmitByte(ModRMByte(0, RegOpcodeField, 5), CurByte, OS);
 
@@ -486,7 +483,7 @@ void X86MCCodeEmitter::EmitMemModRMByte(const MCInst &MI, unsigned Op,
       BaseRegNo != N86::ESP &&
       // If there is no base register and we're in 64-bit mode, we need a SIB
       // byte to emit an addr that is just 'disp32' (the non-RIP relative form).
-      (!is64BitMode() || BaseReg != 0)) {
+      (!is64BitMode(MI) || BaseReg != 0)) {
 
     if (BaseReg == 0) {          // [disp32]     in X86-32 mode
       EmitByte(ModRMByte(0, RegOpcodeField, 5), CurByte, OS);
@@ -1165,18 +1162,18 @@ void X86MCCodeEmitter::EmitOpcodePrefix(uint64_t TSFlags, unsigned &CurByte,
   // The AdSize prefix is only for 32-bit and 64-bit modes; in 16-bit mode we
   // need the address override only for JECXZ instead. Since it's only one
   // instruction, we special-case it rather than introducing an AdSize16 bit.
-  if ((!is16BitMode() && TSFlags & X86II::AdSize) ||
-      (is16BitMode() && MI.getOpcode() == X86::JECXZ_32)) {
+  if ((!is16BitMode(MI) && TSFlags & X86II::AdSize) ||
+      (is16BitMode(MI) && MI.getOpcode() == X86::JECXZ_32)) {
     need_address_override = true;
   } else if (MemOperand == -1) {
     need_address_override = false;
-  } else if (is64BitMode()) {
+  } else if (is64BitMode(MI)) {
     assert(!Is16BitMemOperand(MI, MemOperand));
     need_address_override = Is32BitMemOperand(MI, MemOperand);
-  } else if (is16BitMode()) {
+  } else if (is16BitMode(MI)) {
     assert(!Is64BitMemOperand(MI, MemOperand));
     need_address_override = !Is16BitMemOperand(MI, MemOperand);
-  } else if (is32BitMode()) {
+  } else if (is32BitMode(MI)) {
     assert(!Is64BitMemOperand(MI, MemOperand));
     need_address_override = Is16BitMemOperand(MI, MemOperand);
   } else {
@@ -1187,7 +1184,7 @@ void X86MCCodeEmitter::EmitOpcodePrefix(uint64_t TSFlags, unsigned &CurByte,
     EmitByte(0x67, CurByte, OS);
 
   // Emit the operand size opcode prefix as needed.
-  if (TSFlags & (is16BitMode() ? X86II::OpSize16 : X86II::OpSize))
+  if (TSFlags & (is16BitMode(MI) ? X86II::OpSize16 : X86II::OpSize))
     EmitByte(0x66, CurByte, OS);
 
   bool Need0FPrefix = false;
@@ -1234,7 +1231,7 @@ void X86MCCodeEmitter::EmitOpcodePrefix(uint64_t TSFlags, unsigned &CurByte,
 
   // Handle REX prefix.
   // FIXME: Can this come before F2 etc to simplify emission?
-  if (is64BitMode()) {
+  if (is64BitMode(MI)) {
     if (unsigned REX = DetermineREXPrefix(MI, TSFlags, Desc))
       EmitByte(0x40 | REX, CurByte, OS);
   }
@@ -1269,6 +1266,7 @@ EncodeInstruction(const MCInst &MI, raw_ostream &OS,
   unsigned Opcode = MI.getOpcode();
   const MCInstrDesc &Desc = MCII.get(Opcode);
   uint64_t TSFlags = Desc.TSFlags;
+  assert(MI.isAvailableFeaturesSet() && "Available features not set on instruction");
 
   // Pseudo instructions don't get encoded.
   if ((TSFlags & X86II::FormMask) == X86II::Pseudo)
diff --git a/lib/Target/X86/X86MCInstLower.cpp b/lib/Target/X86/X86MCInstLower.cpp
index b7668d4..10ed6d1 100644
--- a/lib/Target/X86/X86MCInstLower.cpp
+++ b/lib/Target/X86/X86MCInstLower.cpp
@@ -256,8 +256,10 @@ static void SimplifyShortImmForm(MCInst &Inst, unsigned Opcode) {
 
   // If so, rewrite the instruction.
   MCOperand Saved = Inst.getOperand(ImmOp);
+  uint64_t Features = Inst.getAvailableFeatures();
   Inst = MCInst();
   Inst.setOpcode(Opcode);
+  Inst.setAvailableFeatures(Features);
   Inst.addOperand(Saved);
 }
 
@@ -265,6 +267,7 @@ static void SimplifyShortImmForm(MCInst &Inst, unsigned Opcode) {
 /// simplify the instruction to use it instead.
 static void SimplifyMOVSX(MCInst &Inst) {
   unsigned NewOpcode = 0;
+  uint64_t Features = Inst.getAvailableFeatures();
   unsigned Op0 = Inst.getOperand(0).getReg(), Op1 = Inst.getOperand(1).getReg();
   switch (Inst.getOpcode()) {
   default:
@@ -286,6 +289,7 @@ static void SimplifyMOVSX(MCInst &Inst) {
   if (NewOpcode != 0) {
     Inst = MCInst();
     Inst.setOpcode(NewOpcode);
+    Inst.setAvailableFeatures(Features);
   }
 }
 
@@ -335,14 +339,16 @@ static void SimplifyShortMoveForm(X86AsmPrinter &Printer, MCInst &Inst,
 
   // If so, rewrite the instruction.
   MCOperand Saved = Inst.getOperand(AddrOp);
+  uint64_t Features = Inst.getAvailableFeatures();
   Inst = MCInst();
   Inst.setOpcode(Opcode);
+  Inst.setAvailableFeatures(Features);
   Inst.addOperand(Saved);
 }
 
 void X86MCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
   OutMI.setOpcode(MI->getOpcode());
-
+  OutMI.setAvailableFeatures(AsmPrinter.getSubtarget().getFeatureBits());
   for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
     const MachineOperand &MO = MI->getOperand(i);
 
@@ -462,6 +468,7 @@ ReSimplify:
     MCOperand Saved = OutMI.getOperand(0);
     OutMI = MCInst();
     OutMI.setOpcode(Opcode);
+    OutMI.setAvailableFeatures(AsmPrinter.getSubtarget().getFeatureBits());
     OutMI.addOperand(Saved);
     break;
   }
@@ -470,6 +477,7 @@ ReSimplify:
   case X86::EH_RETURN64: {
     OutMI = MCInst();
     OutMI.setOpcode(AsmPrinter.getSubtarget().is64Bit() ? X86::RETQ : X86::RETL);
+    OutMI.setAvailableFeatures(AsmPrinter.getSubtarget().getFeatureBits());
     break;
   }
 
@@ -488,6 +496,7 @@ ReSimplify:
     MCOperand Saved = OutMI.getOperand(0);
     OutMI = MCInst();
     OutMI.setOpcode(Opcode);
+    OutMI.setAvailableFeatures(AsmPrinter.getSubtarget().getFeatureBits());
     OutMI.addOperand(Saved);
     break;
   }
@@ -603,6 +612,7 @@ ReSimplify:
 
 static void LowerTlsAddr(MCStreamer &OutStreamer,
                          X86MCInstLower &MCInstLowering,
+                         uint64_t AvailableFeatures,
                          const MachineInstr &MI) {
 
   bool is64Bits = MI.getOpcode() == X86::TLS_addr64 ||
@@ -613,7 +623,7 @@ static void LowerTlsAddr(MCStreamer &OutStreamer,
   MCContext &context = OutStreamer.getContext();
 
   if (needsPadding)
-    OutStreamer.EmitInstruction(MCInstBuilder(X86::DATA16_PREFIX));
+    OutStreamer.EmitInstruction(MCInstBuilder(X86::DATA16_PREFIX, AvailableFeatures));
 
   MCSymbolRefExpr::VariantKind SRVK;
   switch (MI.getOpcode()) {
@@ -635,6 +645,8 @@ static void LowerTlsAddr(MCStreamer &OutStreamer,
   const MCSymbolRefExpr *symRef = MCSymbolRefExpr::Create(sym, SRVK, context);
 
   MCInst LEA;
+  LEA.setAvailableFeatures(AvailableFeatures);
+
   if (is64Bits) {
     LEA.setOpcode(X86::LEA64r);
     LEA.addOperand(MCOperand::CreateReg(X86::RDI)); // dest
@@ -663,9 +675,9 @@ static void LowerTlsAddr(MCStreamer &OutStreamer,
   OutStreamer.EmitInstruction(LEA);
 
   if (needsPadding) {
-    OutStreamer.EmitInstruction(MCInstBuilder(X86::DATA16_PREFIX));
-    OutStreamer.EmitInstruction(MCInstBuilder(X86::DATA16_PREFIX));
-    OutStreamer.EmitInstruction(MCInstBuilder(X86::REX64_PREFIX));
+    OutStreamer.EmitInstruction(MCInstBuilder(X86::DATA16_PREFIX, AvailableFeatures));
+    OutStreamer.EmitInstruction(MCInstBuilder(X86::DATA16_PREFIX, AvailableFeatures));
+    OutStreamer.EmitInstruction(MCInstBuilder(X86::REX64_PREFIX, AvailableFeatures));
   }
 
   StringRef name = is64Bits ? "__tls_get_addr" : "___tls_get_addr";
@@ -676,15 +688,16 @@ static void LowerTlsAddr(MCStreamer &OutStreamer,
                             context);
 
   OutStreamer.EmitInstruction(MCInstBuilder(is64Bits ? X86::CALL64pcrel32
-                                                     : X86::CALLpcrel32)
+                                                     : X86::CALLpcrel32,
+                                            AvailableFeatures)
     .addExpr(tlsRef));
 }
 
 /// \brief Emit the optimal amount of multi-byte nops on X86.
-static void EmitNops(MCStreamer &OS, unsigned NumBytes, bool Is64Bit) {
+static void EmitNops(MCStreamer &OS, unsigned NumBytes, uint64_t AvailableFeatures) {
   // This works only for 64bit. For 32bit we have to do additional checking if
   // the CPU supports multi-byte nops.
-  assert(Is64Bit && "EmitNops only supports X86-64");
+  assert((AvailableFeatures & X86::Mode64Bit) && "EmitNops only supports X86-64");
   while (NumBytes) {
     unsigned Opc, BaseReg, ScaleVal, IndexReg, Displacement, SegmentReg;
     Opc = IndexReg = Displacement = SegmentReg = 0;
@@ -716,17 +729,18 @@ static void EmitNops(MCStreamer &OS, unsigned NumBytes, bool Is64Bit) {
     switch (Opc) {
     default: llvm_unreachable("Unexpected opcode"); break;
     case X86::NOOP:
-      OS.EmitInstruction(MCInstBuilder(Opc));
+      OS.EmitInstruction(MCInstBuilder(Opc, AvailableFeatures));
       break;
     case X86::XCHG16ar:
-      OS.EmitInstruction(MCInstBuilder(Opc).addReg(X86::AX));
+      OS.EmitInstruction(MCInstBuilder(Opc, AvailableFeatures).addReg(X86::AX));
       break;
     case X86::NOOPL:
     case X86::NOOPW:
-      OS.EmitInstruction(MCInstBuilder(Opc).addReg(BaseReg).addImm(ScaleVal)
-                                           .addReg(IndexReg)
-                                           .addImm(Displacement)
-                                           .addReg(SegmentReg));
+      OS.EmitInstruction(MCInstBuilder(Opc,
+                             AvailableFeatures).addReg(BaseReg).addImm(ScaleVal)
+                                               .addReg(IndexReg)
+                                               .addImm(Displacement)
+                                               .addReg(SegmentReg));
       break;
     }
   } // while (NumBytes)
@@ -735,21 +749,21 @@ static void EmitNops(MCStreamer &OS, unsigned NumBytes, bool Is64Bit) {
 // Lower a stackmap of the form:
 // <id>, <shadowBytes>, ...
 static void LowerSTACKMAP(MCStreamer &OS, StackMaps &SM,
-                          const MachineInstr &MI, bool Is64Bit) {
+                          const MachineInstr &MI, uint64_t AvailableFeatures) {
   unsigned NumBytes = MI.getOperand(1).getImm();
   SM.recordStackMap(MI);
   // Emit padding.
   // FIXME: These nops ensure that the stackmap's shadow is covered by
   // instructions from the same basic block, but the nops should not be
   // necessary if instructions from the same block follow the stackmap.
-  EmitNops(OS, NumBytes, Is64Bit);
+  EmitNops(OS, NumBytes, AvailableFeatures);
 }
 
 // Lower a patchpoint of the form:
 // [<def>], <id>, <numBytes>, <target>, <numArgs>, <cc>, ...
 static void LowerPATCHPOINT(MCStreamer &OS, StackMaps &SM,
-                            const MachineInstr &MI, bool Is64Bit) {
-  assert(Is64Bit && "Patchpoint currently only supports X86-64");
+                            const MachineInstr &MI, uint64_t AvailableFeatures) {
+  assert((AvailableFeatures & X86::Mode64Bit) && "Patchpoint currently only supports X86-64");
   SM.recordPatchPoint(MI);
 
   PatchPointOpers opers(&MI);
@@ -764,19 +778,22 @@ static void LowerPATCHPOINT(MCStreamer &OS, StackMaps &SM,
       EncodedBytes = 13;
     else
       EncodedBytes = 12;
-    OS.EmitInstruction(MCInstBuilder(X86::MOV64ri).addReg(ScratchReg)
+    OS.EmitInstruction(MCInstBuilder(X86::MOV64ri, AvailableFeatures)
+                                                  .addReg(ScratchReg)
                                                   .addImm(CallTarget));
-    OS.EmitInstruction(MCInstBuilder(X86::CALL64r).addReg(ScratchReg));
+    OS.EmitInstruction(MCInstBuilder(X86::CALL64r, AvailableFeatures)
+                                                  .addReg(ScratchReg));
   }
   // Emit padding.
   unsigned NumBytes = opers.getMetaOper(PatchPointOpers::NBytesPos).getImm();
   assert(NumBytes >= EncodedBytes &&
          "Patchpoint can't request size less than the length of a call.");
 
-  EmitNops(OS, NumBytes - EncodedBytes, Is64Bit);
+  EmitNops(OS, NumBytes - EncodedBytes, AvailableFeatures);
 }
 
 void X86AsmPrinter::EmitInstruction(const MachineInstr *MI) {
+  uint64_t AvailableFeatures = Subtarget->getFeatureBits();
   X86MCInstLower MCInstLowering(*MF, *this);
   switch (MI->getOpcode()) {
   case TargetOpcode::DBG_VALUE:
@@ -808,7 +825,7 @@ void X86AsmPrinter::EmitInstruction(const MachineInstr *MI) {
   case X86::TLS_addr64:
   case X86::TLS_base_addr32:
   case X86::TLS_base_addr64:
-    return LowerTlsAddr(OutStreamer, MCInstLowering, *MI);
+    return LowerTlsAddr(OutStreamer, MCInstLowering, AvailableFeatures, *MI);
 
   case X86::MOVPC32r: {
     // This is a pseudo op for a two instruction sequence with a label, which
@@ -821,14 +838,14 @@ void X86AsmPrinter::EmitInstruction(const MachineInstr *MI) {
     MCSymbol *PICBase = MF->getPICBaseSymbol();
     // FIXME: We would like an efficient form for this, so we don't have to do a
     // lot of extra uniquing.
-    OutStreamer.EmitInstruction(MCInstBuilder(X86::CALLpcrel32)
+    OutStreamer.EmitInstruction(MCInstBuilder(X86::CALLpcrel32, AvailableFeatures)
       .addExpr(MCSymbolRefExpr::Create(PICBase, OutContext)));
 
     // Emit the label.
     OutStreamer.EmitLabel(PICBase);
 
     // popl $reg
-    OutStreamer.EmitInstruction(MCInstBuilder(X86::POP32r)
+    OutStreamer.EmitInstruction(MCInstBuilder(X86::POP32r, AvailableFeatures)
       .addReg(MI->getOperand(0).getReg()));
     return;
   }
@@ -859,7 +876,7 @@ void X86AsmPrinter::EmitInstruction(const MachineInstr *MI) {
     DotExpr = MCBinaryExpr::CreateAdd(MCSymbolRefExpr::Create(OpSym,OutContext),
                                       DotExpr, OutContext);
 
-    OutStreamer.EmitInstruction(MCInstBuilder(X86::ADD32ri)
+    OutStreamer.EmitInstruction(MCInstBuilder(X86::ADD32ri, AvailableFeatures)
       .addReg(MI->getOperand(0).getReg())
       .addReg(MI->getOperand(1).getReg())
       .addExpr(DotExpr));
@@ -867,19 +884,21 @@ void X86AsmPrinter::EmitInstruction(const MachineInstr *MI) {
   }
 
   case TargetOpcode::STACKMAP:
-    return LowerSTACKMAP(OutStreamer, SM, *MI, Subtarget->is64Bit());
+    return LowerSTACKMAP(OutStreamer, SM, *MI, AvailableFeatures);
 
   case TargetOpcode::PATCHPOINT:
-    return LowerPATCHPOINT(OutStreamer, SM, *MI, Subtarget->is64Bit());
+    return LowerPATCHPOINT(OutStreamer, SM, *MI, AvailableFeatures);
 
   case X86::MORESTACK_RET:
-    OutStreamer.EmitInstruction(MCInstBuilder(Subtarget->is64Bit() ? X86::RETQ : X86::RETL));
+    OutStreamer.EmitInstruction(MCInstBuilder(Subtarget->is64Bit() ? X86::RETQ : X86::RETL,
+                                              AvailableFeatures));
     return;
 
   case X86::MORESTACK_RET_RESTORE_R10:
     // Return, then restore R10.
-    OutStreamer.EmitInstruction(MCInstBuilder(Subtarget->is64Bit() ? X86::RETQ : X86::RETL));
-    OutStreamer.EmitInstruction(MCInstBuilder(X86::MOV64rr)
+    OutStreamer.EmitInstruction(MCInstBuilder(Subtarget->is64Bit() ? X86::RETQ : X86::RETL,
+                                              AvailableFeatures));
+    OutStreamer.EmitInstruction(MCInstBuilder(X86::MOV64rr, AvailableFeatures)
       .addReg(X86::R10)
       .addReg(X86::RAX));
     return;
@@ -887,5 +906,6 @@ void X86AsmPrinter::EmitInstruction(const MachineInstr *MI) {
 
   MCInst TmpInst;
   MCInstLowering.Lower(MI, TmpInst);
+  assert(TmpInst.isAvailableFeaturesSet() && "Available features not set on instruction");
   OutStreamer.EmitInstruction(TmpInst);
 }


-- 
dwmw2





More information about the llvm-commits mailing list