Move Subzero Assembler traits to the Assembler header/source

Bug: b/192890685
Change-Id: Id4314d3d5494c7cc10df004d8511ac04d4f525ec
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/55848
Presubmit-Ready: Nicolas Capens <nicolascapens@google.com>
Kokoro-Result: kokoro <noreply+kokoro@google.com>
Tested-by: Nicolas Capens <nicolascapens@google.com>
Reviewed-by: Sean Risser <srisser@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/third_party/subzero/src/IceAssemblerX8632.cpp b/third_party/subzero/src/IceAssemblerX8632.cpp
index dbe6da2..83479cd 100644
--- a/third_party/subzero/src/IceAssemblerX8632.cpp
+++ b/third_party/subzero/src/IceAssemblerX8632.cpp
@@ -51,7 +51,7 @@
     }
   }
 
-  GPRRegister Base = Traits::getEncodedGPR(BaseRegNum);
+  GPRRegister Base = Traits::Traits::getEncodedGPR(BaseRegNum);
 
   if (Utils::IsInt(8, Offset)) {
     SetModRM(1, Base);
@@ -86,7 +86,7 @@
     } else if (const auto CR =
                    llvm::dyn_cast<ConstantRelocatable>(Mem->getOffset())) {
       Disp += CR->getOffset();
-      Fixup = Asm->createFixup(Traits::FK_Abs, CR);
+      Fixup = Asm->createFixup(FK_Abs, CR);
     } else {
       llvm_unreachable("Unexpected offset type");
     }
@@ -94,14 +94,14 @@
 
   // Now convert to the various possible forms.
   if (Mem->getBase() && Mem->getIndex()) {
-    SetBaseIndex(getEncodedGPR(Mem->getBase()->getRegNum()),
-                 getEncodedGPR(Mem->getIndex()->getRegNum()),
-                 X8632::Traits::ScaleFactor(Mem->getShift()), Disp, Fixup);
+    SetBaseIndex(Traits::getEncodedGPR(Mem->getBase()->getRegNum()),
+                 Traits::getEncodedGPR(Mem->getIndex()->getRegNum()),
+                 ScaleFactor(Mem->getShift()), Disp, Fixup);
   } else if (Mem->getBase()) {
-    SetBase(getEncodedGPR(Mem->getBase()->getRegNum()), Disp, Fixup);
+    SetBase(Traits::getEncodedGPR(Mem->getBase()->getRegNum()), Disp, Fixup);
   } else if (Mem->getIndex()) {
-    SetIndex(getEncodedGPR(Mem->getIndex()->getRegNum()),
-             X8632::Traits::ScaleFactor(Mem->getShift()), Disp, Fixup);
+    SetIndex(Traits::getEncodedGPR(Mem->getIndex()->getRegNum()),
+             ScaleFactor(Mem->getShift()), Disp, Fixup);
   } else {
     SetAbsolute(Disp, Fixup);
   }
@@ -111,7 +111,7 @@
   assert(!Split->getVar()->hasReg());
   const ::Ice::TargetLowering *Target = Func->getTarget();
   int32_t Offset = Split->getVar()->getStackOffset() + Split->getOffset();
-  SetBase(getEncodedGPR(Target->getFrameOrStackReg()), Offset,
+  SetBase(Traits::getEncodedGPR(Target->getFrameOrStackReg()), Offset,
           AssemblerFixup::NoFixup);
 }
 
@@ -198,7 +198,7 @@
   AssemblerBuffer::EnsureCapacity ensured(&Buffer);
   intptr_t call_start = Buffer.getPosition();
   emitUint8(0xE8);
-  auto *Fixup = this->createFixup(Traits::FK_PcRel, label);
+  auto *Fixup = this->createFixup(FK_PcRel, label);
   Fixup->set_addend(-4);
   emitFixup(Fixup);
   emitInt32(0);
@@ -210,7 +210,7 @@
   AssemblerBuffer::EnsureCapacity ensured(&Buffer);
   intptr_t call_start = Buffer.getPosition();
   emitUint8(0xE8);
-  auto *Fixup = this->createFixup(Traits::FK_PcRel, AssemblerFixup::NullSymbol);
+  auto *Fixup = this->createFixup(FK_PcRel, AssemblerFixup::NullSymbol);
   Fixup->set_addend(abs_address.value() - 4);
   emitFixup(Fixup);
   emitInt32(0);
@@ -232,7 +232,7 @@
 void AssemblerX8632::pushl(const ConstantRelocatable *Label) {
   AssemblerBuffer::EnsureCapacity ensured(&Buffer);
   emitUint8(0x68);
-  emitFixup(this->createFixup(Traits::FK_Abs, Label));
+  emitFixup(this->createFixup(FK_Abs, Label));
   // In x86-32, the emitted value is an addend to the relocation. Therefore, we
   // must emit a 0 (because we're pushing an absolute relocation.)
   // In x86-64, the emitted value does not matter (the addend lives in the
@@ -2153,16 +2153,17 @@
   // the register had high bits set since this only sets flags registers based
   // on the "AND" of the two operands, and the immediate had zeros at those
   // high bits.
-  if (immediate.is_uint8() && reg <= Traits::Last8BitGPR) {
+  constexpr GPRRegister Last8BitGPR = GPRRegister::Encoded_Reg_ebx;
+  if (immediate.is_uint8() && reg <= Last8BitGPR) {
     // Use zero-extended 8-bit immediate.
-    if (reg == Traits::Encoded_Reg_Accumulator) {
+    if (reg == RegX8632::Encoded_Reg_eax) {
       emitUint8(0xA8);
     } else {
       emitUint8(0xF6);
       emitUint8(0xC0 + gprEncoding(reg));
     }
     emitUint8(immediate.value() & 0xFF);
-  } else if (reg == Traits::Encoded_Reg_Accumulator) {
+  } else if (reg == RegX8632::Encoded_Reg_eax) {
     // Use short form if the destination is EAX.
     if (Ty == IceType_i16)
       emitOperandSizeOverride();
@@ -2865,7 +2866,7 @@
   AssemblerBuffer::EnsureCapacity ensured(&Buffer);
   emitUint8(0x0F);
   emitUint8(0x80 + condition);
-  auto *Fixup = this->createFixup(Traits::FK_PcRel, label);
+  auto *Fixup = this->createFixup(FK_PcRel, label);
   Fixup->set_addend(-4);
   emitFixup(Fixup);
   emitInt32(0);
@@ -2903,7 +2904,7 @@
 void AssemblerX8632::jmp(const ConstantRelocatable *label) {
   AssemblerBuffer::EnsureCapacity ensured(&Buffer);
   emitUint8(0xE9);
-  auto *Fixup = this->createFixup(Traits::FK_PcRel, label);
+  auto *Fixup = this->createFixup(FK_PcRel, label);
   Fixup->set_addend(-4);
   emitFixup(Fixup);
   emitInt32(0);
@@ -2913,7 +2914,7 @@
   AssemblerBuffer::EnsureCapacity ensured(&Buffer);
   emitUint8(0xE9);
   AssemblerFixup *Fixup =
-      createFixup(Traits::FK_PcRel, AssemblerFixup::NullSymbol);
+      createFixup(FK_PcRel, AssemblerFixup::NullSymbol);
   Fixup->set_addend(abs_address.value() - 4);
   emitFixup(Fixup);
   emitInt32(0);
@@ -2975,9 +2976,9 @@
   if (Ty == IceType_i16)
     emitOperandSizeOverride();
   // Use short form if either register is EAX.
-  if (reg0 == Traits::Encoded_Reg_Accumulator) {
+  if (reg0 == RegX8632::Encoded_Reg_eax) {
     emitUint8(0x90 + gprEncoding(reg1));
-  } else if (reg1 == Traits::Encoded_Reg_Accumulator) {
+  } else if (reg1 == RegX8632::Encoded_Reg_eax) {
     emitUint8(0x90 + gprEncoding(reg0));
   } else {
     if (isByteSizedArithType(Ty))
@@ -3134,7 +3135,7 @@
                                    const Immediate &immediate) {
   assert(rm >= 0 && rm < 8);
   assert(immediate.is_int8());
-  if (operand.IsRegister(Traits::Encoded_Reg_Accumulator)) {
+  if (operand.IsRegister(RegX8632::Encoded_Reg_eax)) {
     // Use short form if the destination is al.
     emitUint8(0x04 + (rm << 3));
     emitUint8(immediate.value() & 0xFF);
@@ -3156,7 +3157,7 @@
     static constexpr RelocOffsetT OffsetFromNextInstruction = 1;
     emitOperand(rm, operand, OffsetFromNextInstruction);
     emitUint8(immediate.value() & 0xFF);
-  } else if (operand.IsRegister(Traits::Encoded_Reg_Accumulator)) {
+  } else if (operand.IsRegister(RegX8632::Encoded_Reg_eax)) {
     // Use short form if the destination is eax.
     emitUint8(0x05 + (rm << 3));
     emitImmediate(Ty, immediate);
@@ -3216,7 +3217,7 @@
                                       const AsmOperand &operand,
                                       GPRRegister shifter) {
   AssemblerBuffer::EnsureCapacity ensured(&Buffer);
-  assert(shifter == Traits::Encoded_Reg_Counter);
+  assert(shifter == RegX8632::Encoded_Reg_ecx);
   (void)shifter;
   if (Ty == IceType_i16)
     emitOperandSizeOverride();
diff --git a/third_party/subzero/src/IceAssemblerX8632.h b/third_party/subzero/src/IceAssemblerX8632.h
index d4c1716..b845b0b 100644
--- a/third_party/subzero/src/IceAssemblerX8632.h
+++ b/third_party/subzero/src/IceAssemblerX8632.h
@@ -35,13 +35,200 @@
 namespace X8632 {
 
 using Traits = TargetX8632Traits;
-using AsmAddress = typename Traits::AsmAddress;
 using ByteRegister = typename Traits::ByteRegister;
 using BrCond = CondX86::BrCond;
 using CmppsCond = CondX86::CmppsCond;
 using GPRRegister = typename Traits::GPRRegister;
-using AsmOperand = typename Traits::AsmOperand;
 using XmmRegister = typename Traits::XmmRegister;
+using X86OperandMem = typename Traits::X86OperandMem;
+using VariableSplit = typename Traits::VariableSplit;
+
+constexpr FixupKind FK_PcRel = llvm::ELF::R_386_PC32;
+constexpr FixupKind FK_Abs = llvm::ELF::R_386_32;
+constexpr FixupKind FK_Gotoff = llvm::ELF::R_386_GOTOFF;
+constexpr FixupKind FK_GotPC = llvm::ELF::R_386_GOTPC;
+
+enum ScaleFactor { TIMES_1 = 0, TIMES_2 = 1, TIMES_4 = 2, TIMES_8 = 3 };
+
+class AsmOperand {
+public:
+  AsmOperand(const AsmOperand &other)
+      : fixup_(other.fixup_), length_(other.length_) {
+    memmove(&encoding_[0], &other.encoding_[0], other.length_);
+  }
+
+  AsmOperand &operator=(const AsmOperand &other) {
+    length_ = other.length_;
+    fixup_ = other.fixup_;
+    memmove(&encoding_[0], &other.encoding_[0], other.length_);
+    return *this;
+  }
+
+  uint8_t mod() const { return (encoding_at(0) >> 6) & 3; }
+
+  GPRRegister rm() const {
+    return static_cast<GPRRegister>(encoding_at(0) & 7);
+  }
+
+  ScaleFactor scale() const {
+    return static_cast<ScaleFactor>((encoding_at(1) >> 6) & 3);
+  }
+
+  GPRRegister index() const {
+    return static_cast<GPRRegister>((encoding_at(1) >> 3) & 7);
+  }
+
+  GPRRegister base() const {
+    return static_cast<GPRRegister>(encoding_at(1) & 7);
+  }
+
+  int8_t disp8() const {
+    assert(length_ >= 2);
+    return static_cast<int8_t>(encoding_[length_ - 1]);
+  }
+
+  AssemblerFixup *fixup() const { return fixup_; }
+
+protected:
+  AsmOperand()
+      : fixup_(nullptr), length_(0) {} // Needed by subclass AsmAddress.
+
+  void SetModRM(int mod, GPRRegister rm) {
+    assert((mod & ~3) == 0);
+    encoding_[0] = (mod << 6) | rm;
+    length_ = 1;
+  }
+
+  void SetSIB(ScaleFactor scale, GPRRegister index, GPRRegister base) {
+    assert(length_ == 1);
+    assert((scale & ~3) == 0);
+    encoding_[1] = (scale << 6) | (index << 3) | base;
+    length_ = 2;
+  }
+
+  void SetDisp8(int8_t disp) {
+    assert(length_ == 1 || length_ == 2);
+    encoding_[length_++] = static_cast<uint8_t>(disp);
+  }
+
+  void SetDisp32(int32_t disp) {
+    assert(length_ == 1 || length_ == 2);
+    intptr_t disp_size = sizeof(disp);
+    memmove(&encoding_[length_], &disp, disp_size);
+    length_ += disp_size;
+  }
+
+  void SetFixup(AssemblerFixup *fixup) { fixup_ = fixup; }
+
+private:
+  AssemblerFixup *fixup_;
+  uint8_t encoding_[6];
+  uint8_t length_;
+
+  explicit AsmOperand(GPRRegister reg) : fixup_(nullptr) { SetModRM(3, reg); }
+
+  /// Get the operand encoding byte at the given index.
+  uint8_t encoding_at(intptr_t index) const {
+    assert(index >= 0 && index < length_);
+    return encoding_[index];
+  }
+
+  /// Returns whether or not this operand is really the given register in
+  /// disguise. Used from the assembler to generate better encodings.
+  bool IsRegister(GPRRegister reg) const {
+    return ((encoding_[0] & 0xF8) == 0xC0) // Addressing mode is register only.
+           && ((encoding_[0] & 0x07) == reg); // Register codes match.
+  }
+
+  friend class AssemblerX8632;
+};
+
+class AsmAddress : public AsmOperand {
+  AsmAddress() = delete;
+
+public:
+  AsmAddress(GPRRegister Base, int32_t Disp, AssemblerFixup *Fixup = nullptr) {
+    SetBase(Base, Disp, Fixup);
+  }
+  AsmAddress(const Variable *Var, const TargetX8632 *Target);
+  AsmAddress(const X86OperandMem *Mem, Ice::Assembler *Asm,
+             const Ice::TargetLowering *Target);
+  AsmAddress(const VariableSplit *Split, const Cfg *Func);
+
+  // Address into the constant pool.
+  AsmAddress(const Constant *Imm, Ice::Assembler *Asm) {
+    AssemblerFixup *Fixup = Asm->createFixup(llvm::ELF::R_386_32, Imm);
+    const RelocOffsetT Offset = 0;
+    SetAbsolute(Offset, Fixup);
+  }
+
+private:
+  AsmAddress(const AsmAddress &other) : AsmOperand(other) {}
+
+  AsmAddress &operator=(const AsmAddress &other) {
+    AsmOperand::operator=(other);
+    return *this;
+  }
+
+  void SetBase(GPRRegister Base, int32_t Disp, AssemblerFixup *Fixup) {
+    if (Fixup == nullptr && Disp == 0 && Base != RegX8632::Encoded_Reg_ebp) {
+      SetModRM(0, Base);
+      if (Base == RegX8632::Encoded_Reg_esp)
+        SetSIB(TIMES_1, RegX8632::Encoded_Reg_esp, Base);
+    } else if (Fixup == nullptr && Utils::IsInt(8, Disp)) {
+      SetModRM(1, Base);
+      if (Base == RegX8632::Encoded_Reg_esp)
+        SetSIB(TIMES_1, RegX8632::Encoded_Reg_esp, Base);
+      SetDisp8(Disp);
+    } else {
+      SetModRM(2, Base);
+      if (Base == RegX8632::Encoded_Reg_esp)
+        SetSIB(TIMES_1, RegX8632::Encoded_Reg_esp, Base);
+      SetDisp32(Disp);
+      if (Fixup)
+        SetFixup(Fixup);
+    }
+  }
+
+  void SetIndex(GPRRegister Index, ScaleFactor Scale, int32_t Disp,
+                AssemblerFixup *Fixup) {
+    assert(Index != RegX8632::Encoded_Reg_esp); // Illegal addressing mode.
+    SetModRM(0, RegX8632::Encoded_Reg_esp);
+    SetSIB(Scale, Index, RegX8632::Encoded_Reg_ebp);
+    SetDisp32(Disp);
+    if (Fixup)
+      SetFixup(Fixup);
+  }
+
+  void SetBaseIndex(GPRRegister Base, GPRRegister Index, ScaleFactor Scale,
+                    int32_t Disp, AssemblerFixup *Fixup) {
+    assert(Index != RegX8632::Encoded_Reg_esp); // Illegal addressing mode.
+    if (Fixup == nullptr && Disp == 0 && Base != RegX8632::Encoded_Reg_ebp) {
+      SetModRM(0, RegX8632::Encoded_Reg_esp);
+      SetSIB(Scale, Index, Base);
+    } else if (Fixup == nullptr && Utils::IsInt(8, Disp)) {
+      SetModRM(1, RegX8632::Encoded_Reg_esp);
+      SetSIB(Scale, Index, Base);
+      SetDisp8(Disp);
+    } else {
+      SetModRM(2, RegX8632::Encoded_Reg_esp);
+      SetSIB(Scale, Index, Base);
+      SetDisp32(Disp);
+      if (Fixup)
+        SetFixup(Fixup);
+    }
+  }
+
+  /// Generate an absolute address expression on x86-32.
+  void SetAbsolute(RelocOffsetT Offset, AssemblerFixup *Fixup) {
+    SetModRM(0, RegX8632::Encoded_Reg_ebp);
+    // Use the Offset in the displacement for now. If we decide to process
+    // fixups later, we'll need to patch up the emitted displacement.
+    SetDisp32(Offset);
+    if (Fixup)
+      SetFixup(Fixup);
+  }
+};
 
 class AssemblerX8632 : public ::Ice::Assembler {
   AssemblerX8632(const AssemblerX8632 &) = delete;
@@ -162,7 +349,7 @@
   bool fixupIsPCRel(FixupKind Kind) const override {
     // Currently assuming this is the only PC-rel relocation type used.
     // TODO(jpp): Traits.PcRelTypes.count(Kind) != 0
-    return Kind == Traits::FK_PcRel;
+    return Kind == FK_PcRel;
   }
 
   // Operations to emit GPR instructions (and dispatch on operand type).
diff --git a/third_party/subzero/src/IceAssemblerX8664.cpp b/third_party/subzero/src/IceAssemblerX8664.cpp
index 24c4c10..6994a36 100644
--- a/third_party/subzero/src/IceAssemblerX8664.cpp
+++ b/third_party/subzero/src/IceAssemblerX8664.cpp
@@ -50,7 +50,8 @@
       BaseRegNum = Target->getFrameOrStackReg();
     }
   }
-  SetBase(Traits::getEncodedGPR(BaseRegNum), Offset, AssemblerFixup::NoFixup);
+  SetBase(Traits::Traits::getEncodedGPR(BaseRegNum), Offset,
+          AssemblerFixup::NoFixup);
 }
 
 AsmAddress::AsmAddress(const X86OperandMem *Mem, Ice::Assembler *Asm,
@@ -85,14 +86,14 @@
 
   // Now convert to the various possible forms.
   if (Mem->getBase() && Mem->getIndex()) {
-    SetBaseIndex(getEncodedGPR(Mem->getBase()->getRegNum()),
-                 getEncodedGPR(Mem->getIndex()->getRegNum()),
-                 X8664::Traits::ScaleFactor(Mem->getShift()), Disp, Fixup);
+    SetBaseIndex(Traits::getEncodedGPR(Mem->getBase()->getRegNum()),
+                 Traits::getEncodedGPR(Mem->getIndex()->getRegNum()),
+                 ScaleFactor(Mem->getShift()), Disp, Fixup);
   } else if (Mem->getBase()) {
-    SetBase(getEncodedGPR(Mem->getBase()->getRegNum()), Disp, Fixup);
+    SetBase(Traits::getEncodedGPR(Mem->getBase()->getRegNum()), Disp, Fixup);
   } else if (Mem->getIndex()) {
-    SetIndex(getEncodedGPR(Mem->getIndex()->getRegNum()),
-             X8664::Traits::ScaleFactor(Mem->getShift()), Disp, Fixup);
+    SetIndex(Traits::getEncodedGPR(Mem->getIndex()->getRegNum()),
+             ScaleFactor(Mem->getShift()), Disp, Fixup);
   } else if (Fixup == nullptr) {
     SetAbsolute(Disp);
   } else {
@@ -185,7 +186,7 @@
   AssemblerBuffer::EnsureCapacity ensured(&Buffer);
   intptr_t call_start = Buffer.getPosition();
   emitUint8(0xE8);
-  auto *Fixup = this->createFixup(Traits::FK_PcRel, label);
+  auto *Fixup = this->createFixup(FK_PcRel, label);
   Fixup->set_addend(-4);
   emitFixup(Fixup);
   emitInt32(0);
@@ -197,7 +198,7 @@
   AssemblerBuffer::EnsureCapacity ensured(&Buffer);
   intptr_t call_start = Buffer.getPosition();
   emitUint8(0xE8);
-  auto *Fixup = this->createFixup(Traits::FK_PcRel, AssemblerFixup::NullSymbol);
+  auto *Fixup = this->createFixup(FK_PcRel, AssemblerFixup::NullSymbol);
   Fixup->set_addend(abs_address.value() - 4);
   emitFixup(Fixup);
   emitInt32(0);
@@ -220,7 +221,7 @@
 void AssemblerX8664::pushl(const ConstantRelocatable *Label) {
   AssemblerBuffer::EnsureCapacity ensured(&Buffer);
   emitUint8(0x68);
-  emitFixup(this->createFixup(Traits::FK_Abs, Label));
+  emitFixup(this->createFixup(FK_Abs, Label));
   // In x86-32, the emitted value is an addend to the relocation. Therefore, we
   // must emit a 0 (because we're pushing an absolute relocation.)
   // In x86-64, the emitted value does not matter (the addend lives in the
@@ -2277,17 +2278,18 @@
   // the register had high bits set since this only sets flags registers based
   // on the "AND" of the two operands, and the immediate had zeros at those
   // high bits.
-  if (immediate.is_uint8() && reg <= Traits::Last8BitGPR) {
+  constexpr GPRRegister Last8BitGPR = GPRRegister::Encoded_Reg_r15d;
+  if (immediate.is_uint8() && reg <= Last8BitGPR) {
     // Use zero-extended 8-bit immediate.
     emitRexB(Ty, reg);
-    if (reg == Traits::Encoded_Reg_Accumulator) {
+    if (reg == RegX8664::Encoded_Reg_rax) {
       emitUint8(0xA8);
     } else {
       emitUint8(0xF6);
       emitUint8(0xC0 + gprEncoding(reg));
     }
     emitUint8(immediate.value() & 0xFF);
-  } else if (reg == Traits::Encoded_Reg_Accumulator) {
+  } else if (reg == RegX8664::Encoded_Reg_rax) {
     // Use short form if the destination is EAX.
     if (Ty == IceType_i16)
       emitOperandSizeOverride();
@@ -3019,7 +3021,7 @@
   AssemblerBuffer::EnsureCapacity ensured(&Buffer);
   emitUint8(0x0F);
   emitUint8(0x80 + condition);
-  auto *Fixup = this->createFixup(Traits::FK_PcRel, label);
+  auto *Fixup = this->createFixup(FK_PcRel, label);
   Fixup->set_addend(-4);
   emitFixup(Fixup);
   emitInt32(0);
@@ -3058,7 +3060,7 @@
 void AssemblerX8664::jmp(const ConstantRelocatable *label) {
   AssemblerBuffer::EnsureCapacity ensured(&Buffer);
   emitUint8(0xE9);
-  auto *Fixup = this->createFixup(Traits::FK_PcRel, label);
+  auto *Fixup = this->createFixup(FK_PcRel, label);
   Fixup->set_addend(-4);
   emitFixup(Fixup);
   emitInt32(0);
@@ -3067,8 +3069,7 @@
 void AssemblerX8664::jmp(const Immediate &abs_address) {
   AssemblerBuffer::EnsureCapacity ensured(&Buffer);
   emitUint8(0xE9);
-  AssemblerFixup *Fixup =
-      createFixup(Traits::FK_PcRel, AssemblerFixup::NullSymbol);
+  AssemblerFixup *Fixup = createFixup(FK_PcRel, AssemblerFixup::NullSymbol);
   Fixup->set_addend(abs_address.value() - 4);
   emitFixup(Fixup);
   emitInt32(0);
@@ -3132,11 +3133,11 @@
   AssemblerBuffer::EnsureCapacity ensured(&Buffer);
   if (Ty == IceType_i16)
     emitOperandSizeOverride();
-  // Use short form if either register is EAX.
-  if (reg0 == Traits::Encoded_Reg_Accumulator) {
+  // Use short form if either register is RAX.
+  if (reg0 == RegX8664::Encoded_Reg_rax) {
     emitRexB(Ty, reg1);
     emitUint8(0x90 + gprEncoding(reg1));
-  } else if (reg1 == Traits::Encoded_Reg_Accumulator) {
+  } else if (reg1 == RegX8664::Encoded_Reg_rax) {
     emitRexB(Ty, reg0);
     emitUint8(0x90 + gprEncoding(reg0));
   } else {
@@ -3298,7 +3299,7 @@
                                    const Immediate &immediate) {
   assert(rm >= 0 && rm < 8);
   assert(immediate.is_int8());
-  if (operand.IsRegister(Traits::Encoded_Reg_Accumulator)) {
+  if (operand.IsRegister(RegX8664::Encoded_Reg_rax)) {
     // Use short form if the destination is al.
     emitUint8(0x04 + (rm << 3));
     emitUint8(immediate.value() & 0xFF);
@@ -3320,7 +3321,7 @@
     static constexpr RelocOffsetT OffsetFromNextInstruction = 1;
     emitOperand(rm, operand, OffsetFromNextInstruction);
     emitUint8(immediate.value() & 0xFF);
-  } else if (operand.IsRegister(Traits::Encoded_Reg_Accumulator)) {
+  } else if (operand.IsRegister(RegX8664::Encoded_Reg_rax)) {
     // Use short form if the destination is eax.
     emitUint8(0x05 + (rm << 3));
     emitImmediate(Ty, immediate);
@@ -3381,7 +3382,7 @@
                                       const AsmOperand &operand,
                                       GPRRegister shifter) {
   AssemblerBuffer::EnsureCapacity ensured(&Buffer);
-  assert(shifter == Traits::Encoded_Reg_Counter);
+  assert(shifter == RegX8664::Encoded_Reg_rcx);
   (void)shifter;
   if (Ty == IceType_i16)
     emitOperandSizeOverride();
diff --git a/third_party/subzero/src/IceAssemblerX8664.h b/third_party/subzero/src/IceAssemblerX8664.h
index 457a572..dbab294 100644
--- a/third_party/subzero/src/IceAssemblerX8664.h
+++ b/third_party/subzero/src/IceAssemblerX8664.h
@@ -35,13 +35,221 @@
 namespace X8664 {
 
 using Traits = TargetX8664Traits;
-using AsmAddress = typename Traits::AsmAddress;
 using ByteRegister = typename Traits::ByteRegister;
 using BrCond = CondX86::BrCond;
 using CmppsCond = CondX86::CmppsCond;
 using GPRRegister = typename Traits::GPRRegister;
-using AsmOperand = typename Traits::AsmOperand;
 using XmmRegister = typename Traits::XmmRegister;
+using X86OperandMem = typename Traits::X86OperandMem;
+
+constexpr FixupKind FK_PcRel = llvm::ELF::R_X86_64_PC32;
+constexpr FixupKind FK_Abs = llvm::ELF::R_X86_64_32S;
+constexpr FixupKind FK_Gotoff = llvm::ELF::R_X86_64_GOTOFF64;
+constexpr FixupKind FK_GotPC = llvm::ELF::R_X86_64_GOTPC32;
+
+enum ScaleFactor { TIMES_1 = 0, TIMES_2 = 1, TIMES_4 = 2, TIMES_8 = 3 };
+
+class AsmOperand {
+public:
+  enum RexBits {
+    RexNone = 0x00,
+    RexBase = 0x40,
+    RexW = RexBase | (1 << 3),
+    RexR = RexBase | (1 << 2),
+    RexX = RexBase | (1 << 1),
+    RexB = RexBase | (1 << 0),
+  };
+
+protected:
+  // Needed by subclass AsmAddress.
+  AsmOperand() = default;
+
+public:
+  AsmOperand(const AsmOperand &) = default;
+  AsmOperand(AsmOperand &&) = default;
+  AsmOperand &operator=(const AsmOperand &) = default;
+  AsmOperand &operator=(AsmOperand &&) = default;
+
+  uint8_t mod() const { return (encoding_at(0) >> 6) & 3; }
+
+  uint8_t rexX() const { return (rex_ & RexX) != RexX ? RexNone : RexX; }
+  uint8_t rexB() const { return (rex_ & RexB) != RexB ? RexNone : RexB; }
+
+  GPRRegister rm() const {
+    return static_cast<GPRRegister>((rexB() != 0 ? 0x08 : 0) |
+                                    (encoding_at(0) & 7));
+  }
+
+  ScaleFactor scale() const {
+    return static_cast<ScaleFactor>((encoding_at(1) >> 6) & 3);
+  }
+
+  GPRRegister index() const {
+    return static_cast<GPRRegister>((rexX() != 0 ? 0x08 : 0) |
+                                    ((encoding_at(1) >> 3) & 7));
+  }
+
+  GPRRegister base() const {
+    return static_cast<GPRRegister>((rexB() != 0 ? 0x08 : 0) |
+                                    (encoding_at(1) & 7));
+  }
+
+  int8_t disp8() const {
+    assert(length_ >= 2);
+    return static_cast<int8_t>(encoding_[length_ - 1]);
+  }
+
+  AssemblerFixup *fixup() const { return fixup_; }
+
+protected:
+  void SetModRM(int mod, GPRRegister rm) {
+    assert((mod & ~3) == 0);
+    encoding_[0] = (mod << 6) | (rm & 0x07);
+    rex_ = (rm & 0x08) ? RexB : RexNone;
+    length_ = 1;
+  }
+
+  void SetSIB(ScaleFactor scale, GPRRegister index, GPRRegister base) {
+    assert(length_ == 1);
+    assert((scale & ~3) == 0);
+    encoding_[1] = (scale << 6) | ((index & 0x07) << 3) | (base & 0x07);
+    rex_ = ((base & 0x08) ? RexB : RexNone) | ((index & 0x08) ? RexX : RexNone);
+    length_ = 2;
+  }
+
+  void SetDisp8(int8_t disp) {
+    assert(length_ == 1 || length_ == 2);
+    encoding_[length_++] = static_cast<uint8_t>(disp);
+  }
+
+  void SetDisp32(int32_t disp) {
+    assert(length_ == 1 || length_ == 2);
+    intptr_t disp_size = sizeof(disp);
+    memmove(&encoding_[length_], &disp, disp_size);
+    length_ += disp_size;
+  }
+
+  void SetFixup(AssemblerFixup *fixup) { fixup_ = fixup; }
+
+private:
+  AssemblerFixup *fixup_ = nullptr;
+  uint8_t rex_ = 0;
+  uint8_t encoding_[6];
+  uint8_t length_ = 0;
+
+  explicit AsmOperand(GPRRegister reg) : fixup_(nullptr) { SetModRM(3, reg); }
+
+  /// Get the operand encoding byte at the given index.
+  uint8_t encoding_at(intptr_t index) const {
+    assert(index >= 0 && index < length_);
+    return encoding_[index];
+  }
+
+  /// Returns whether or not this operand is really the given register in
+  /// disguise. Used from the assembler to generate better encodings.
+  bool IsRegister(GPRRegister reg) const {
+    return ((encoding_[0] & 0xF8) == 0xC0) // Addressing mode is register only.
+           && (rm() == reg);               // Register codes match.
+  }
+
+  friend class AssemblerX8664;
+};
+
+class AsmAddress : public AsmOperand {
+  AsmAddress() = default;
+
+public:
+  AsmAddress(const Variable *Var, const TargetX8664 *Target);
+  AsmAddress(const X86OperandMem *Mem, Ice::Assembler *Asm,
+             const Ice::TargetLowering *Target);
+
+  // Address into the constant pool.
+  AsmAddress(const Constant *Imm, Ice::Assembler *Asm) {
+    // TODO(jpp): ???
+    AssemblerFixup *Fixup = Asm->createFixup(FK_Abs, Imm);
+    const RelocOffsetT Offset = 4;
+    SetRipRelative(Offset, Fixup);
+  }
+
+private:
+  AsmAddress(const AsmAddress &) = default;
+  AsmAddress(AsmAddress &&) = default;
+  AsmAddress &operator=(const AsmAddress &) = default;
+  AsmAddress &operator=(AsmAddress &&) = default;
+
+  void SetBase(GPRRegister Base, int32_t Disp, AssemblerFixup *Fixup) {
+    if (Fixup == nullptr && Disp == 0 &&
+        (Base & 7) != RegX8664::Encoded_Reg_rbp) {
+      SetModRM(0, Base);
+      if ((Base & 7) == RegX8664::Encoded_Reg_rsp)
+        SetSIB(TIMES_1, RegX8664::Encoded_Reg_rsp, Base);
+    } else if (Fixup == nullptr && Utils::IsInt(8, Disp)) {
+      SetModRM(1, Base);
+      if ((Base & 7) == RegX8664::Encoded_Reg_rsp)
+        SetSIB(TIMES_1, RegX8664::Encoded_Reg_rsp, Base);
+      SetDisp8(Disp);
+    } else {
+      SetModRM(2, Base);
+      if ((Base & 7) == RegX8664::Encoded_Reg_rsp)
+        SetSIB(TIMES_1, RegX8664::Encoded_Reg_rsp, Base);
+      SetDisp32(Disp);
+      if (Fixup)
+        SetFixup(Fixup);
+    }
+  }
+
+  void SetIndex(GPRRegister Index, ScaleFactor Scale, int32_t Disp,
+                AssemblerFixup *Fixup) {
+    assert(Index != RegX8664::Encoded_Reg_rsp); // Illegal addressing mode.
+    SetModRM(0, RegX8664::Encoded_Reg_rsp);
+    SetSIB(Scale, Index, RegX8664::Encoded_Reg_rbp);
+    SetDisp32(Disp);
+    if (Fixup)
+      SetFixup(Fixup);
+  }
+
+  void SetBaseIndex(GPRRegister Base, GPRRegister Index, ScaleFactor Scale,
+                    int32_t Disp, AssemblerFixup *Fixup) {
+    assert(Index != RegX8664::Encoded_Reg_rsp); // Illegal addressing mode.
+    if (Fixup == nullptr && Disp == 0 &&
+        (Base & 7) != RegX8664::Encoded_Reg_rbp) {
+      SetModRM(0, RegX8664::Encoded_Reg_rsp);
+      SetSIB(Scale, Index, Base);
+    } else if (Fixup == nullptr && Utils::IsInt(8, Disp)) {
+      SetModRM(1, RegX8664::Encoded_Reg_rsp);
+      SetSIB(Scale, Index, Base);
+      SetDisp8(Disp);
+    } else {
+      SetModRM(2, RegX8664::Encoded_Reg_rsp);
+      SetSIB(Scale, Index, Base);
+      SetDisp32(Disp);
+      if (Fixup)
+        SetFixup(Fixup);
+    }
+  }
+
+  /// Generate a RIP-relative address expression on x86-64.
+  void SetRipRelative(RelocOffsetT Offset, AssemblerFixup *Fixup) {
+    assert(Fixup != nullptr);
+    assert(Fixup->kind() == FK_PcRel);
+
+    SetModRM(0x0, RegX8664::Encoded_Reg_rbp);
+
+    // Use the Offset in the displacement for now. If we decide to process
+    // fixups later, we'll need to patch up the emitted displacement.
+    SetDisp32(Offset);
+    if (Fixup)
+      SetFixup(Fixup);
+  }
+
+  /// Generate an absolute address.
+  void SetAbsolute(RelocOffsetT Addr) {
+    SetModRM(0x0, RegX8664::Encoded_Reg_rsp);
+    static constexpr ScaleFactor NoScale = TIMES_1;
+    SetSIB(NoScale, RegX8664::Encoded_Reg_rsp, RegX8664::Encoded_Reg_rbp);
+    SetDisp32(Addr);
+  }
+};
 
 class AssemblerX8664 : public ::Ice::Assembler {
   AssemblerX8664(const AssemblerX8664 &) = delete;
@@ -162,7 +370,7 @@
   bool fixupIsPCRel(FixupKind Kind) const override {
     // Currently assuming this is the only PC-rel relocation type used.
     // TODO(jpp): Traits.PcRelTypes.count(Kind) != 0
-    return Kind == Traits::FK_PcRel;
+    return Kind == FK_PcRel;
   }
 
   // Operations to emit GPR instructions (and dispatch on operand type).
diff --git a/third_party/subzero/src/IceInstX8632.cpp b/third_party/subzero/src/IceInstX8632.cpp
index f82679c..51ff578 100644
--- a/third_party/subzero/src/IceInstX8632.cpp
+++ b/third_party/subzero/src/IceInstX8632.cpp
@@ -622,8 +622,8 @@
   } else if (const auto *Reloc = llvm::dyn_cast<ConstantRelocatable>(Src)) {
     const auto FixupKind = (Reloc->getName().hasStdString() &&
                             Reloc->getName().toString() == GlobalOffsetTable)
-                               ? Traits::FK_GotPC
-                               : Traits::FK_Abs;
+                               ? FK_GotPC
+                               : FK_Abs;
     AssemblerFixup *Fixup = Asm->createFixup(FixupKind, Reloc);
     (Asm->*(Emitter.GPRImm))(Ty, VarReg, AssemblerImmediate(Fixup));
   } else if (const auto *Split = llvm::dyn_cast<VariableSplit>(Src)) {
@@ -646,8 +646,8 @@
   } else if (const auto *Reloc = llvm::dyn_cast<ConstantRelocatable>(Src)) {
     const auto FixupKind = (Reloc->getName().hasStdString() &&
                             Reloc->getName().toString() == GlobalOffsetTable)
-                               ? Traits::FK_GotPC
-                               : Traits::FK_Abs;
+                               ? FK_GotPC
+                               : FK_Abs;
     AssemblerFixup *Fixup = Asm->createFixup(FixupKind, Reloc);
     (Asm->*(Emitter.AddrImm))(Ty, Addr, AssemblerImmediate(Fixup));
   } else {
diff --git a/third_party/subzero/src/IceInstX8632.h b/third_party/subzero/src/IceInstX8632.h
index e38d627..782df58 100644
--- a/third_party/subzero/src/IceInstX8632.h
+++ b/third_party/subzero/src/IceInstX8632.h
@@ -34,7 +34,6 @@
 using Assembler = typename Traits::Assembler;
 using AssemblerImmediate = typename Assembler::Immediate;
 using TargetLowering = typename Traits::TargetLowering;
-using AsmAddress = typename Traits::AsmAddress;
 using X86Operand = typename Traits::X86Operand;
 using X86OperandMem = typename Traits::X86OperandMem;
 using VariableSplit = typename Traits::VariableSplit;
diff --git a/third_party/subzero/src/IceInstX8664.cpp b/third_party/subzero/src/IceInstX8664.cpp
index 39f5212..71e7773 100644
--- a/third_party/subzero/src/IceInstX8664.cpp
+++ b/third_party/subzero/src/IceInstX8664.cpp
@@ -625,8 +625,8 @@
   } else if (const auto *Reloc = llvm::dyn_cast<ConstantRelocatable>(Src)) {
     const auto FixupKind = (Reloc->getName().hasStdString() &&
                             Reloc->getName().toString() == GlobalOffsetTable)
-                               ? Traits::FK_GotPC
-                               : Traits::FK_Abs;
+                               ? FK_GotPC
+                               : FK_Abs;
     AssemblerFixup *Fixup = Asm->createFixup(FixupKind, Reloc);
     (Asm->*(Emitter.GPRImm))(Ty, VarReg, AssemblerImmediate(Fixup));
   } else {
@@ -650,8 +650,8 @@
   } else if (const auto *Reloc = llvm::dyn_cast<ConstantRelocatable>(Src)) {
     const auto FixupKind = (Reloc->getName().hasStdString() &&
                             Reloc->getName().toString() == GlobalOffsetTable)
-                               ? Traits::FK_GotPC
-                               : Traits::FK_Abs;
+                               ? FK_GotPC
+                               : FK_Abs;
     AssemblerFixup *Fixup = Asm->createFixup(FixupKind, Reloc);
     (Asm->*(Emitter.AddrImm))(Ty, Addr, AssemblerImmediate(Fixup));
   } else {
diff --git a/third_party/subzero/src/IceInstX8664.h b/third_party/subzero/src/IceInstX8664.h
index f0aa3fa..02582c8 100644
--- a/third_party/subzero/src/IceInstX8664.h
+++ b/third_party/subzero/src/IceInstX8664.h
@@ -34,7 +34,6 @@
 using Assembler = typename Traits::Assembler;
 using AssemblerImmediate = typename Assembler::Immediate;
 using TargetLowering = typename Traits::TargetLowering;
-using AsmAddress = typename Traits::AsmAddress;
 using X86Operand = typename Traits::X86Operand;
 using X86OperandMem = typename Traits::X86OperandMem;
 
diff --git a/third_party/subzero/src/IceTargetLoweringX8632.cpp b/third_party/subzero/src/IceTargetLoweringX8632.cpp
index 3489fec..0381a53 100644
--- a/third_party/subzero/src/IceTargetLoweringX8632.cpp
+++ b/third_party/subzero/src/IceTargetLoweringX8632.cpp
@@ -7822,7 +7822,7 @@
   switch (getFlags().getOutFileType()) {
   case FT_Elf: {
     ELFObjectWriter *Writer = Ctx->getObjectWriter();
-    const FixupKind RelocationKind = Traits::FK_Abs;
+    const FixupKind RelocationKind = FK_Abs;
     for (const JumpTableData &JT : Ctx->getJumpTables())
       Writer->writeJumpTable(JT, RelocationKind, IsPIC);
   } break;
@@ -7856,7 +7856,7 @@
   switch (getFlags().getOutFileType()) {
   case FT_Elf: {
     ELFObjectWriter *Writer = Ctx->getObjectWriter();
-    Writer->writeDataSection(Vars, Traits::FK_Abs, SectionSuffix, IsPIC);
+    Writer->writeDataSection(Vars, FK_Abs, SectionSuffix, IsPIC);
   } break;
   case FT_Asm:
   case FT_Iasm: {
diff --git a/third_party/subzero/src/IceTargetLoweringX8632.h b/third_party/subzero/src/IceTargetLoweringX8632.h
index 463ae2e..52e28b3 100644
--- a/third_party/subzero/src/IceTargetLoweringX8632.h
+++ b/third_party/subzero/src/IceTargetLoweringX8632.h
@@ -126,7 +126,6 @@
   using BrCond = CondX86::BrCond;
   using CmppsCond = CondX86::CmppsCond;
 
-  using AsmAddress = typename Traits::AsmAddress;
   using X86Operand = typename Traits::X86Operand;
   using X86OperandMem = typename Traits::X86OperandMem;
   using SegmentRegisters = typename Traits::X86OperandMem::SegmentRegisters;
@@ -205,8 +204,8 @@
 
   bool hasFramePointer() const override { return IsEbpBasedFrame; }
   void setHasFramePointer() override { IsEbpBasedFrame = true; }
-  RegNumT getStackReg() const override { return Traits::StackPtr; }
-  RegNumT getFrameReg() const override { return Traits::FramePtr; }
+  RegNumT getStackReg() const override { return RegX8632::Reg_esp; }
+  RegNumT getFrameReg() const override { return RegX8632::Reg_ebp; }
   RegNumT getFrameOrStackReg() const override {
     // If the stack pointer needs to be aligned, then the frame pointer is
     // unaligned, so always use the stack pointer.
@@ -957,9 +956,6 @@
                                       int8_t Idx14, int8_t Idx15);
   /// @}
 
-  static constexpr FixupKind PcRelFixup = Traits::FK_PcRel;
-  static constexpr FixupKind AbsFixup = Traits::FK_Abs;
-
 public:
   static std::unique_ptr<::Ice::TargetLowering> create(Cfg *Func) {
     return makeUnique<TargetX8632>(Func);
diff --git a/third_party/subzero/src/IceTargetLoweringX8632Traits.h b/third_party/subzero/src/IceTargetLoweringX8632Traits.h
index 4fa67b2..ac5fa32 100644
--- a/third_party/subzero/src/IceTargetLoweringX8632Traits.h
+++ b/third_party/subzero/src/IceTargetLoweringX8632Traits.h
@@ -38,219 +38,11 @@
 class TargetX8632;
 
 struct TargetX8632Traits {
-  //----------------------------------------------------------------------------
-  //     ______  ______  __    __
-  //    /\  __ \/\  ___\/\ "-./  \
-  //    \ \  __ \ \___  \ \ \-./\ \
-  //     \ \_\ \_\/\_____\ \_\ \ \_\
-  //      \/_/\/_/\/_____/\/_/  \/_/
-  //
-  //----------------------------------------------------------------------------
-  static constexpr ::Ice::RegX8632::GPRRegister Last8BitGPR =
-      ::Ice::RegX8632::GPRRegister::Encoded_Reg_ebx;
-
-  enum ScaleFactor { TIMES_1 = 0, TIMES_2 = 1, TIMES_4 = 2, TIMES_8 = 3 };
-
-  using GPRRegister = ::Ice::RegX8632::GPRRegister;
-  using ByteRegister = ::Ice::RegX8632::ByteRegister;
-  using XmmRegister = ::Ice::RegX8632::XmmRegister;
-  using X87STRegister = ::Ice::RegX8632::X87STRegister;
-
   using RegisterSet = ::Ice::RegX8632;
-  static constexpr RegisterSet::AllRegisters StackPtr = RegX8632::Reg_esp;
-  static constexpr RegisterSet::AllRegisters FramePtr = RegX8632::Reg_ebp;
-  static constexpr GPRRegister Encoded_Reg_Accumulator =
-      RegX8632::Encoded_Reg_eax;
-  static constexpr GPRRegister Encoded_Reg_Counter = RegX8632::Encoded_Reg_ecx;
-  static constexpr FixupKind FK_PcRel = llvm::ELF::R_386_PC32;
-  static constexpr FixupKind FK_Abs = llvm::ELF::R_386_32;
-  static constexpr FixupKind FK_Gotoff = llvm::ELF::R_386_GOTOFF;
-  static constexpr FixupKind FK_GotPC = llvm::ELF::R_386_GOTPC;
-
-  class X86OperandMem;
-  class VariableSplit;
-
-  class AsmOperand {
-  public:
-    AsmOperand(const AsmOperand &other)
-        : fixup_(other.fixup_), length_(other.length_) {
-      memmove(&encoding_[0], &other.encoding_[0], other.length_);
-    }
-
-    AsmOperand &operator=(const AsmOperand &other) {
-      length_ = other.length_;
-      fixup_ = other.fixup_;
-      memmove(&encoding_[0], &other.encoding_[0], other.length_);
-      return *this;
-    }
-
-    uint8_t mod() const { return (encoding_at(0) >> 6) & 3; }
-
-    GPRRegister rm() const {
-      return static_cast<GPRRegister>(encoding_at(0) & 7);
-    }
-
-    ScaleFactor scale() const {
-      return static_cast<ScaleFactor>((encoding_at(1) >> 6) & 3);
-    }
-
-    GPRRegister index() const {
-      return static_cast<GPRRegister>((encoding_at(1) >> 3) & 7);
-    }
-
-    GPRRegister base() const {
-      return static_cast<GPRRegister>(encoding_at(1) & 7);
-    }
-
-    int8_t disp8() const {
-      assert(length_ >= 2);
-      return static_cast<int8_t>(encoding_[length_ - 1]);
-    }
-
-    AssemblerFixup *fixup() const { return fixup_; }
-
-  protected:
-    AsmOperand()
-        : fixup_(nullptr), length_(0) {} // Needed by subclass AsmAddress.
-
-    void SetModRM(int mod, GPRRegister rm) {
-      assert((mod & ~3) == 0);
-      encoding_[0] = (mod << 6) | rm;
-      length_ = 1;
-    }
-
-    void SetSIB(ScaleFactor scale, GPRRegister index, GPRRegister base) {
-      assert(length_ == 1);
-      assert((scale & ~3) == 0);
-      encoding_[1] = (scale << 6) | (index << 3) | base;
-      length_ = 2;
-    }
-
-    void SetDisp8(int8_t disp) {
-      assert(length_ == 1 || length_ == 2);
-      encoding_[length_++] = static_cast<uint8_t>(disp);
-    }
-
-    void SetDisp32(int32_t disp) {
-      assert(length_ == 1 || length_ == 2);
-      intptr_t disp_size = sizeof(disp);
-      memmove(&encoding_[length_], &disp, disp_size);
-      length_ += disp_size;
-    }
-
-    void SetFixup(AssemblerFixup *fixup) { fixup_ = fixup; }
-
-  private:
-    AssemblerFixup *fixup_;
-    uint8_t encoding_[6];
-    uint8_t length_;
-
-    explicit AsmOperand(GPRRegister reg) : fixup_(nullptr) { SetModRM(3, reg); }
-
-    /// Get the operand encoding byte at the given index.
-    uint8_t encoding_at(intptr_t index) const {
-      assert(index >= 0 && index < length_);
-      return encoding_[index];
-    }
-
-    /// Returns whether or not this operand is really the given register in
-    /// disguise. Used from the assembler to generate better encodings.
-    bool IsRegister(GPRRegister reg) const {
-      return ((encoding_[0] & 0xF8) ==
-              0xC0) // Addressing mode is register only.
-             && ((encoding_[0] & 0x07) == reg); // Register codes match.
-    }
-
-    friend class AssemblerX8632;
-  };
-
-  class AsmAddress : public AsmOperand {
-    AsmAddress() = delete;
-
-  public:
-    AsmAddress(GPRRegister Base, int32_t Disp,
-               AssemblerFixup *Fixup = nullptr) {
-      SetBase(Base, Disp, Fixup);
-    }
-    AsmAddress(const Variable *Var, const TargetX8632 *Target);
-    AsmAddress(const X86OperandMem *Mem, Ice::Assembler *Asm,
-               const Ice::TargetLowering *Target);
-    AsmAddress(const VariableSplit *Split, const Cfg *Func);
-
-    // Address into the constant pool.
-    AsmAddress(const Constant *Imm, Ice::Assembler *Asm) {
-      AssemblerFixup *Fixup = Asm->createFixup(llvm::ELF::R_386_32, Imm);
-      const RelocOffsetT Offset = 0;
-      SetAbsolute(Offset, Fixup);
-    }
-
-  private:
-    AsmAddress(const AsmAddress &other) : AsmOperand(other) {}
-
-    AsmAddress &operator=(const AsmAddress &other) {
-      AsmOperand::operator=(other);
-      return *this;
-    }
-
-    void SetBase(GPRRegister Base, int32_t Disp, AssemblerFixup *Fixup) {
-      if (Fixup == nullptr && Disp == 0 && Base != RegX8632::Encoded_Reg_ebp) {
-        SetModRM(0, Base);
-        if (Base == RegX8632::Encoded_Reg_esp)
-          SetSIB(TIMES_1, RegX8632::Encoded_Reg_esp, Base);
-      } else if (Fixup == nullptr && Utils::IsInt(8, Disp)) {
-        SetModRM(1, Base);
-        if (Base == RegX8632::Encoded_Reg_esp)
-          SetSIB(TIMES_1, RegX8632::Encoded_Reg_esp, Base);
-        SetDisp8(Disp);
-      } else {
-        SetModRM(2, Base);
-        if (Base == RegX8632::Encoded_Reg_esp)
-          SetSIB(TIMES_1, RegX8632::Encoded_Reg_esp, Base);
-        SetDisp32(Disp);
-        if (Fixup)
-          SetFixup(Fixup);
-      }
-    }
-
-    void SetIndex(GPRRegister Index, ScaleFactor Scale, int32_t Disp,
-                  AssemblerFixup *Fixup) {
-      assert(Index != RegX8632::Encoded_Reg_esp); // Illegal addressing mode.
-      SetModRM(0, RegX8632::Encoded_Reg_esp);
-      SetSIB(Scale, Index, RegX8632::Encoded_Reg_ebp);
-      SetDisp32(Disp);
-      if (Fixup)
-        SetFixup(Fixup);
-    }
-
-    void SetBaseIndex(GPRRegister Base, GPRRegister Index, ScaleFactor Scale,
-                      int32_t Disp, AssemblerFixup *Fixup) {
-      assert(Index != RegX8632::Encoded_Reg_esp); // Illegal addressing mode.
-      if (Fixup == nullptr && Disp == 0 && Base != RegX8632::Encoded_Reg_ebp) {
-        SetModRM(0, RegX8632::Encoded_Reg_esp);
-        SetSIB(Scale, Index, Base);
-      } else if (Fixup == nullptr && Utils::IsInt(8, Disp)) {
-        SetModRM(1, RegX8632::Encoded_Reg_esp);
-        SetSIB(Scale, Index, Base);
-        SetDisp8(Disp);
-      } else {
-        SetModRM(2, RegX8632::Encoded_Reg_esp);
-        SetSIB(Scale, Index, Base);
-        SetDisp32(Disp);
-        if (Fixup)
-          SetFixup(Fixup);
-      }
-    }
-
-    /// Generate an absolute address expression on x86-32.
-    void SetAbsolute(RelocOffsetT Offset, AssemblerFixup *Fixup) {
-      SetModRM(0, RegX8632::Encoded_Reg_ebp);
-      // Use the Offset in the displacement for now. If we decide to process
-      // fixups later, we'll need to patch up the emitted displacement.
-      SetDisp32(Offset);
-      if (Fixup)
-        SetFixup(Fixup);
-    }
-  };
+  using GPRRegister = RegisterSet::GPRRegister;
+  using ByteRegister = RegisterSet::ByteRegister;
+  using XmmRegister = RegisterSet::XmmRegister;
+  using X87STRegister = RegisterSet::X87STRegister;
 
   //----------------------------------------------------------------------------
   //     __      ______  __     __  ______  ______  __  __   __  ______
diff --git a/third_party/subzero/src/IceTargetLoweringX8664.cpp b/third_party/subzero/src/IceTargetLoweringX8664.cpp
index c411d12..a782914 100644
--- a/third_party/subzero/src/IceTargetLoweringX8664.cpp
+++ b/third_party/subzero/src/IceTargetLoweringX8664.cpp
@@ -7067,7 +7067,7 @@
     ELFObjectWriter *Writer = Ctx->getObjectWriter();
     constexpr FixupKind FK_Abs64 = llvm::ELF::R_X86_64_64;
     const FixupKind RelocationKind =
-        (getPointerType() == IceType_i32) ? Traits::FK_Abs : FK_Abs64;
+        (getPointerType() == IceType_i32) ? FK_Abs : FK_Abs64;
     for (const JumpTableData &JT : Ctx->getJumpTables())
       Writer->writeJumpTable(JT, RelocationKind, IsPIC);
   } break;
@@ -7101,7 +7101,7 @@
   switch (getFlags().getOutFileType()) {
   case FT_Elf: {
     ELFObjectWriter *Writer = Ctx->getObjectWriter();
-    Writer->writeDataSection(Vars, Traits::FK_Abs, SectionSuffix, IsPIC);
+    Writer->writeDataSection(Vars, FK_Abs, SectionSuffix, IsPIC);
   } break;
   case FT_Asm:
   case FT_Iasm: {
diff --git a/third_party/subzero/src/IceTargetLoweringX8664.h b/third_party/subzero/src/IceTargetLoweringX8664.h
index e84d29d..b31134a 100644
--- a/third_party/subzero/src/IceTargetLoweringX8664.h
+++ b/third_party/subzero/src/IceTargetLoweringX8664.h
@@ -127,7 +127,6 @@
   using BrCond = CondX86::BrCond;
   using CmppsCond = CondX86::CmppsCond;
 
-  using AsmAddress = typename Traits::AsmAddress;
   using X86Operand = typename Traits::X86Operand;
   using X86OperandMem = typename Traits::X86OperandMem;
   using SegmentRegisters = typename Traits::X86OperandMem::SegmentRegisters;
@@ -206,8 +205,8 @@
 
   bool hasFramePointer() const override { return IsEbpBasedFrame; }
   void setHasFramePointer() override { IsEbpBasedFrame = true; }
-  RegNumT getStackReg() const override { return Traits::StackPtr; }
-  RegNumT getFrameReg() const override { return Traits::FramePtr; }
+  RegNumT getStackReg() const override { return RegX8664::Reg_rsp; }
+  RegNumT getFrameReg() const override { return RegX8664::Reg_rbp; }
   RegNumT getFrameOrStackReg() const override {
     // If the stack pointer needs to be aligned, then the frame pointer is
     // unaligned, so always use the stack pointer.
@@ -945,9 +944,6 @@
                                       int8_t Idx14, int8_t Idx15);
   /// @}
 
-  static constexpr FixupKind PcRelFixup = Traits::FK_PcRel;
-  static constexpr FixupKind AbsFixup = Traits::FK_Abs;
-
 public:
   static std::unique_ptr<::Ice::TargetLowering> create(Cfg *Func) {
     return makeUnique<TargetX8664>(Func);
diff --git a/third_party/subzero/src/IceTargetLoweringX8664Traits.h b/third_party/subzero/src/IceTargetLoweringX8664Traits.h
index bba2281..5c8734a 100644
--- a/third_party/subzero/src/IceTargetLoweringX8664Traits.h
+++ b/third_party/subzero/src/IceTargetLoweringX8664Traits.h
@@ -39,239 +39,10 @@
 class TargetX8664;
 
 struct TargetX8664Traits {
-  //----------------------------------------------------------------------------
-  //     ______  ______  __    __
-  //    /\  __ \/\  ___\/\ "-./  \
-  //    \ \  __ \ \___  \ \ \-./\ \
-  //     \ \_\ \_\/\_____\ \_\ \ \_\
-  //      \/_/\/_/\/_____/\/_/  \/_/
-  //
-  //----------------------------------------------------------------------------
-  static constexpr ::Ice::RegX8664::GPRRegister Last8BitGPR =
-      ::Ice::RegX8664::GPRRegister::Encoded_Reg_r15d;
-
-  enum ScaleFactor { TIMES_1 = 0, TIMES_2 = 1, TIMES_4 = 2, TIMES_8 = 3 };
-
-  using GPRRegister = ::Ice::RegX8664::GPRRegister;
-  using ByteRegister = ::Ice::RegX8664::ByteRegister;
-  using XmmRegister = ::Ice::RegX8664::XmmRegister;
-
   using RegisterSet = ::Ice::RegX8664;
-  static constexpr RegisterSet::AllRegisters StackPtr = RegX8664::Reg_rsp;
-  static constexpr RegisterSet::AllRegisters FramePtr = RegX8664::Reg_rbp;
-  static constexpr GPRRegister Encoded_Reg_Accumulator =
-      RegX8664::Encoded_Reg_eax;
-  static constexpr GPRRegister Encoded_Reg_Counter = RegX8664::Encoded_Reg_ecx;
-  static constexpr FixupKind FK_PcRel = llvm::ELF::R_X86_64_PC32;
-  static constexpr FixupKind FK_Abs = llvm::ELF::R_X86_64_32S;
-  static constexpr FixupKind FK_Gotoff = llvm::ELF::R_X86_64_GOTOFF64;
-  static constexpr FixupKind FK_GotPC = llvm::ELF::R_X86_64_GOTPC32;
-
-  class X86OperandMem;
-
-  class AsmOperand {
-  public:
-    enum RexBits {
-      RexNone = 0x00,
-      RexBase = 0x40,
-      RexW = RexBase | (1 << 3),
-      RexR = RexBase | (1 << 2),
-      RexX = RexBase | (1 << 1),
-      RexB = RexBase | (1 << 0),
-    };
-
-  protected:
-    // Needed by subclass AsmAddress.
-    AsmOperand() = default;
-
-  public:
-    AsmOperand(const AsmOperand &) = default;
-    AsmOperand(AsmOperand &&) = default;
-    AsmOperand &operator=(const AsmOperand &) = default;
-    AsmOperand &operator=(AsmOperand &&) = default;
-
-    uint8_t mod() const { return (encoding_at(0) >> 6) & 3; }
-
-    uint8_t rexX() const { return (rex_ & RexX) != RexX ? RexNone : RexX; }
-    uint8_t rexB() const { return (rex_ & RexB) != RexB ? RexNone : RexB; }
-
-    GPRRegister rm() const {
-      return static_cast<GPRRegister>((rexB() != 0 ? 0x08 : 0) |
-                                      (encoding_at(0) & 7));
-    }
-
-    ScaleFactor scale() const {
-      return static_cast<ScaleFactor>((encoding_at(1) >> 6) & 3);
-    }
-
-    GPRRegister index() const {
-      return static_cast<GPRRegister>((rexX() != 0 ? 0x08 : 0) |
-                                      ((encoding_at(1) >> 3) & 7));
-    }
-
-    GPRRegister base() const {
-      return static_cast<GPRRegister>((rexB() != 0 ? 0x08 : 0) |
-                                      (encoding_at(1) & 7));
-    }
-
-    int8_t disp8() const {
-      assert(length_ >= 2);
-      return static_cast<int8_t>(encoding_[length_ - 1]);
-    }
-
-    AssemblerFixup *fixup() const { return fixup_; }
-
-  protected:
-    void SetModRM(int mod, GPRRegister rm) {
-      assert((mod & ~3) == 0);
-      encoding_[0] = (mod << 6) | (rm & 0x07);
-      rex_ = (rm & 0x08) ? RexB : RexNone;
-      length_ = 1;
-    }
-
-    void SetSIB(ScaleFactor scale, GPRRegister index, GPRRegister base) {
-      assert(length_ == 1);
-      assert((scale & ~3) == 0);
-      encoding_[1] = (scale << 6) | ((index & 0x07) << 3) | (base & 0x07);
-      rex_ =
-          ((base & 0x08) ? RexB : RexNone) | ((index & 0x08) ? RexX : RexNone);
-      length_ = 2;
-    }
-
-    void SetDisp8(int8_t disp) {
-      assert(length_ == 1 || length_ == 2);
-      encoding_[length_++] = static_cast<uint8_t>(disp);
-    }
-
-    void SetDisp32(int32_t disp) {
-      assert(length_ == 1 || length_ == 2);
-      intptr_t disp_size = sizeof(disp);
-      memmove(&encoding_[length_], &disp, disp_size);
-      length_ += disp_size;
-    }
-
-    void SetFixup(AssemblerFixup *fixup) { fixup_ = fixup; }
-
-  private:
-    AssemblerFixup *fixup_ = nullptr;
-    uint8_t rex_ = 0;
-    uint8_t encoding_[6];
-    uint8_t length_ = 0;
-
-    explicit AsmOperand(GPRRegister reg) : fixup_(nullptr) { SetModRM(3, reg); }
-
-    /// Get the operand encoding byte at the given index.
-    uint8_t encoding_at(intptr_t index) const {
-      assert(index >= 0 && index < length_);
-      return encoding_[index];
-    }
-
-    /// Returns whether or not this operand is really the given register in
-    /// disguise. Used from the assembler to generate better encodings.
-    bool IsRegister(GPRRegister reg) const {
-      return ((encoding_[0] & 0xF8) ==
-              0xC0)            // Addressing mode is register only.
-             && (rm() == reg); // Register codes match.
-    }
-
-    friend class AssemblerX8664;
-  };
-
-  class AsmAddress : public AsmOperand {
-    AsmAddress() = default;
-
-  public:
-    AsmAddress(const Variable *Var, const TargetX8664 *Target);
-    AsmAddress(const X86OperandMem *Mem, Ice::Assembler *Asm,
-               const Ice::TargetLowering *Target);
-
-    // Address into the constant pool.
-    AsmAddress(const Constant *Imm, Ice::Assembler *Asm) {
-      // TODO(jpp): ???
-      AssemblerFixup *Fixup = Asm->createFixup(FK_Abs, Imm);
-      const RelocOffsetT Offset = 4;
-      SetRipRelative(Offset, Fixup);
-    }
-
-  private:
-    AsmAddress(const AsmAddress &) = default;
-    AsmAddress(AsmAddress &&) = default;
-    AsmAddress &operator=(const AsmAddress &) = default;
-    AsmAddress &operator=(AsmAddress &&) = default;
-
-    void SetBase(GPRRegister Base, int32_t Disp, AssemblerFixup *Fixup) {
-      if (Fixup == nullptr && Disp == 0 &&
-          (Base & 7) != RegX8664::Encoded_Reg_rbp) {
-        SetModRM(0, Base);
-        if ((Base & 7) == RegX8664::Encoded_Reg_rsp)
-          SetSIB(TIMES_1, RegX8664::Encoded_Reg_rsp, Base);
-      } else if (Fixup == nullptr && Utils::IsInt(8, Disp)) {
-        SetModRM(1, Base);
-        if ((Base & 7) == RegX8664::Encoded_Reg_rsp)
-          SetSIB(TIMES_1, RegX8664::Encoded_Reg_rsp, Base);
-        SetDisp8(Disp);
-      } else {
-        SetModRM(2, Base);
-        if ((Base & 7) == RegX8664::Encoded_Reg_rsp)
-          SetSIB(TIMES_1, RegX8664::Encoded_Reg_rsp, Base);
-        SetDisp32(Disp);
-        if (Fixup)
-          SetFixup(Fixup);
-      }
-    }
-
-    void SetIndex(GPRRegister Index, ScaleFactor Scale, int32_t Disp,
-                  AssemblerFixup *Fixup) {
-      assert(Index != RegX8664::Encoded_Reg_rsp); // Illegal addressing mode.
-      SetModRM(0, RegX8664::Encoded_Reg_rsp);
-      SetSIB(Scale, Index, RegX8664::Encoded_Reg_rbp);
-      SetDisp32(Disp);
-      if (Fixup)
-        SetFixup(Fixup);
-    }
-
-    void SetBaseIndex(GPRRegister Base, GPRRegister Index, ScaleFactor Scale,
-                      int32_t Disp, AssemblerFixup *Fixup) {
-      assert(Index != RegX8664::Encoded_Reg_rsp); // Illegal addressing mode.
-      if (Fixup == nullptr && Disp == 0 &&
-          (Base & 7) != RegX8664::Encoded_Reg_rbp) {
-        SetModRM(0, RegX8664::Encoded_Reg_rsp);
-        SetSIB(Scale, Index, Base);
-      } else if (Fixup == nullptr && Utils::IsInt(8, Disp)) {
-        SetModRM(1, RegX8664::Encoded_Reg_rsp);
-        SetSIB(Scale, Index, Base);
-        SetDisp8(Disp);
-      } else {
-        SetModRM(2, RegX8664::Encoded_Reg_rsp);
-        SetSIB(Scale, Index, Base);
-        SetDisp32(Disp);
-        if (Fixup)
-          SetFixup(Fixup);
-      }
-    }
-
-    /// Generate a RIP-relative address expression on x86-64.
-    void SetRipRelative(RelocOffsetT Offset, AssemblerFixup *Fixup) {
-      assert(Fixup != nullptr);
-      assert(Fixup->kind() == FK_PcRel);
-
-      SetModRM(0x0, RegX8664::Encoded_Reg_rbp);
-
-      // Use the Offset in the displacement for now. If we decide to process
-      // fixups later, we'll need to patch up the emitted displacement.
-      SetDisp32(Offset);
-      if (Fixup)
-        SetFixup(Fixup);
-    }
-
-    /// Generate an absolute address.
-    void SetAbsolute(RelocOffsetT Addr) {
-      SetModRM(0x0, RegX8664::Encoded_Reg_rsp);
-      static constexpr ScaleFactor NoScale = TIMES_1;
-      SetSIB(NoScale, RegX8664::Encoded_Reg_rsp, RegX8664::Encoded_Reg_rbp);
-      SetDisp32(Addr);
-    }
-  };
+  using GPRRegister = RegisterSet::GPRRegister;
+  using ByteRegister = RegisterSet::ByteRegister;
+  using XmmRegister = RegisterSet::XmmRegister;
 
   //----------------------------------------------------------------------------
   //     __      ______  __     __  ______  ______  __  __   __  ______