[TableGen] Remove code beads
Code beads is useless since the only user, M68k, has moved on to a new encoding/decoding infrastructure. Reviewed By: myhsu Differential Revision: https://reviews.llvm.org/D126349
This commit is contained in:
@@ -7,7 +7,6 @@ tablegen(LLVM M68kGenRegisterInfo.inc -gen-register-info)
|
||||
tablegen(LLVM M68kGenRegisterBank.inc -gen-register-bank)
|
||||
tablegen(LLVM M68kGenInstrInfo.inc -gen-instr-info)
|
||||
tablegen(LLVM M68kGenSubtargetInfo.inc -gen-subtarget)
|
||||
tablegen(LLVM M68kGenMCCodeBeads.inc -gen-code-beads)
|
||||
tablegen(LLVM M68kGenMCCodeEmitter.inc -gen-emitter)
|
||||
tablegen(LLVM M68kGenMCPseudoLowering.inc -gen-pseudo-lowering)
|
||||
tablegen(LLVM M68kGenDAGISel.inc -gen-dag-isel)
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||
#include "llvm/MC/TargetRegistry.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/Regex.h"
|
||||
|
||||
#include <functional>
|
||||
|
||||
@@ -601,40 +602,26 @@ bool M68kInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
|
||||
bool M68kInstrInfo::isPCRelRegisterOperandLegal(
|
||||
const MachineOperand &MO) const {
|
||||
assert(MO.isReg());
|
||||
const auto *MI = MO.getParent();
|
||||
const uint8_t *Beads = M68k::getMCInstrBeads(MI->getOpcode());
|
||||
assert(*Beads);
|
||||
|
||||
// Only addressing mode k has (non-pc) register with PCRel
|
||||
// So we're looking for EA Beads equal to
|
||||
// `3Bits<011>_1Bit<1>_2Bits<11>`
|
||||
// FIXME: There is an important caveat and two assumptions
|
||||
// here: The caveat is that EA encoding always sit on the LSB.
|
||||
// Where the assumptions are that if there are more than one
|
||||
// operands, the EA encoding for the source operand always sit
|
||||
// on the LSB. At the same time, k addressing mode can not be used
|
||||
// on destination operand.
|
||||
// The last assumption is kinda dirty so we need to find a way around
|
||||
// it
|
||||
const uint8_t EncEAk[3] = {0b011, 0b1, 0b11};
|
||||
for (const uint8_t Pat : EncEAk) {
|
||||
uint8_t Bead = *(Beads++);
|
||||
if (!Bead)
|
||||
return false;
|
||||
// Check whether this MO belongs to an instruction with addressing mode 'k',
|
||||
// Refer to TargetInstrInfo.h for more information about this function.
|
||||
|
||||
switch (Bead & 0xF) {
|
||||
default:
|
||||
return false;
|
||||
case M68kBeads::Bits1:
|
||||
case M68kBeads::Bits2:
|
||||
case M68kBeads::Bits3: {
|
||||
uint8_t Val = (Bead & 0xF0) >> 4;
|
||||
if (Val != Pat)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
const MachineInstr *MI = MO.getParent();
|
||||
const unsigned NameIndices = M68kInstrNameIndices[MI->getOpcode()];
|
||||
StringRef InstrName(&M68kInstrNameData[NameIndices]);
|
||||
const unsigned OperandNo = MI->getOperandNo(&MO);
|
||||
|
||||
// If this machine operand is the 2nd operand, then check
|
||||
// whether the instruction has destination addressing mode 'k'.
|
||||
if (OperandNo == 1)
|
||||
return Regex("[A-Z]+(8|16|32)k[a-z](_TC)?$").match(InstrName);
|
||||
|
||||
// If this machine operand is the last one, then check
|
||||
// whether the instruction has source addressing mode 'k'.
|
||||
if (OperandNo == MI->getNumExplicitOperands() - 1)
|
||||
return Regex("[A-Z]+(8|16|32)[a-z]k(_TC)?$").match(InstrName);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void M68kInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
|
||||
|
||||
@@ -65,26 +65,6 @@ public:
|
||||
|
||||
~M68kMCCodeEmitter() override {}
|
||||
|
||||
// TableGen'erated function
|
||||
const uint8_t *getGenInstrBeads(const MCInst &MI) const {
|
||||
return M68k::getMCInstrBeads(MI.getOpcode());
|
||||
}
|
||||
|
||||
unsigned encodeBits(unsigned ThisByte, uint8_t Bead, const MCInst &MI,
|
||||
const MCInstrDesc &Desc, uint64_t &Buffer,
|
||||
unsigned Offset, SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const;
|
||||
|
||||
unsigned encodeReg(unsigned ThisByte, uint8_t Bead, const MCInst &MI,
|
||||
const MCInstrDesc &Desc, uint64_t &Buffer, unsigned Offset,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const;
|
||||
|
||||
unsigned encodeImm(unsigned ThisByte, uint8_t Bead, const MCInst &MI,
|
||||
const MCInstrDesc &Desc, uint64_t &Buffer, unsigned Offset,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const;
|
||||
|
||||
void encodeInstruction(const MCInst &MI, raw_ostream &OS,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const override;
|
||||
@@ -237,246 +217,6 @@ void M68kMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &Op,
|
||||
}
|
||||
}
|
||||
|
||||
unsigned M68kMCCodeEmitter::encodeBits(unsigned ThisByte, uint8_t Bead,
|
||||
const MCInst &MI,
|
||||
const MCInstrDesc &Desc,
|
||||
uint64_t &Buffer, unsigned Offset,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const {
|
||||
unsigned Num = 0;
|
||||
switch (Bead & 0xF) {
|
||||
case M68kBeads::Bits1:
|
||||
Num = 1;
|
||||
break;
|
||||
case M68kBeads::Bits2:
|
||||
Num = 2;
|
||||
break;
|
||||
case M68kBeads::Bits3:
|
||||
Num = 3;
|
||||
break;
|
||||
case M68kBeads::Bits4:
|
||||
Num = 4;
|
||||
break;
|
||||
}
|
||||
unsigned char Val = (Bead & 0xF0) >> 4;
|
||||
|
||||
LLVM_DEBUG(dbgs() << "\tEncodeBits"
|
||||
<< " Num: " << Num << " Val: 0x");
|
||||
LLVM_DEBUG(dbgs().write_hex(Val) << "\n");
|
||||
|
||||
Buffer |= (Val << Offset);
|
||||
|
||||
return Num;
|
||||
}
|
||||
|
||||
unsigned M68kMCCodeEmitter::encodeReg(unsigned ThisByte, uint8_t Bead,
|
||||
const MCInst &MI, const MCInstrDesc &Desc,
|
||||
uint64_t &Buffer, unsigned Offset,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const {
|
||||
bool DA, Reg;
|
||||
switch (Bead & 0xF) {
|
||||
default:
|
||||
llvm_unreachable("Unrecognized Bead code for register type");
|
||||
case M68kBeads::DAReg:
|
||||
Reg = true;
|
||||
DA = true;
|
||||
break;
|
||||
case M68kBeads::DA:
|
||||
Reg = false;
|
||||
DA = true;
|
||||
break;
|
||||
case M68kBeads::DReg:
|
||||
case M68kBeads::Reg:
|
||||
Reg = true;
|
||||
DA = false;
|
||||
break;
|
||||
}
|
||||
|
||||
unsigned Op = (Bead & 0x70) >> 4;
|
||||
bool Alt = (Bead & 0x80);
|
||||
LLVM_DEBUG(dbgs() << "\tEncodeReg"
|
||||
<< " Op: " << Op << ", DA: " << DA << ", Reg: " << Reg
|
||||
<< ", Alt: " << Alt << "\n");
|
||||
|
||||
auto MIOpIdx = M68k::getLogicalOperandIdx(MI.getOpcode(), Op);
|
||||
bool IsPCRel = Desc.OpInfo[MIOpIdx].OperandType == MCOI::OPERAND_PCREL;
|
||||
|
||||
MCOperand MCO;
|
||||
if (M68kII::hasMultiMIOperands(MI.getOpcode(), Op)) {
|
||||
if (IsPCRel) {
|
||||
assert(Alt &&
|
||||
"PCRel addresses use Alt bead register encoding by default");
|
||||
MCO = MI.getOperand(MIOpIdx + M68k::PCRelIndex);
|
||||
} else {
|
||||
MCO = MI.getOperand(MIOpIdx + (Alt ? M68k::MemIndex : M68k::MemBase));
|
||||
}
|
||||
} else {
|
||||
assert(!Alt && "You cannot use Alt register with a simple operand");
|
||||
MCO = MI.getOperand(MIOpIdx);
|
||||
}
|
||||
|
||||
unsigned RegNum = MCO.getReg();
|
||||
auto RI = Ctx.getRegisterInfo();
|
||||
|
||||
unsigned Written = 0;
|
||||
if (Reg) {
|
||||
uint32_t Val = RI->getEncodingValue(RegNum);
|
||||
Buffer |= (Val & 7) << Offset;
|
||||
Offset += 3;
|
||||
Written += 3;
|
||||
}
|
||||
|
||||
if (DA) {
|
||||
Buffer |= (uint64_t)M68kII::isAddressRegister(RegNum) << Offset;
|
||||
Written++;
|
||||
}
|
||||
|
||||
return Written;
|
||||
}
|
||||
|
||||
static unsigned EmitConstant(uint64_t Val, unsigned Size, unsigned Pad,
|
||||
uint64_t &Buffer, unsigned Offset) {
|
||||
assert(Size + Offset <= 64 && isUIntN(Size, Val) && "Value does not fit");
|
||||
|
||||
// Writing Value in host's endianness
|
||||
Buffer |= (Val & ((1ULL << Size) - 1)) << Offset;
|
||||
return Size + Pad;
|
||||
}
|
||||
|
||||
unsigned M68kMCCodeEmitter::encodeImm(unsigned ThisByte, uint8_t Bead,
|
||||
const MCInst &MI, const MCInstrDesc &Desc,
|
||||
uint64_t &Buffer, unsigned Offset,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const {
|
||||
unsigned ThisWord = ThisByte / 2;
|
||||
unsigned Size = 0;
|
||||
unsigned Pad = 0;
|
||||
unsigned FixOffset = 0;
|
||||
int64_t Addendum = 0;
|
||||
bool NoExpr = false;
|
||||
|
||||
unsigned Type = Bead & 0xF;
|
||||
unsigned Op = (Bead & 0x70) >> 4;
|
||||
bool Alt = (Bead & 0x80);
|
||||
|
||||
auto MIOpIdx = M68k::getLogicalOperandIdx(MI.getOpcode(), Op);
|
||||
bool IsPCRel = Desc.OpInfo[MIOpIdx].OperandType == MCOI::OPERAND_PCREL;
|
||||
|
||||
// The PC value upon instruction reading of a short jump will point to the
|
||||
// next instruction, thus we need to compensate 2 bytes, which is the diff
|
||||
// between the patch point and the PC.
|
||||
if (IsPCRel && ThisWord == 0)
|
||||
Addendum -= 2;
|
||||
|
||||
switch (Type) {
|
||||
// ??? what happens if it is not byte aligned
|
||||
// ??? is it even possible
|
||||
case M68kBeads::Disp8:
|
||||
Size = 8;
|
||||
Pad = 0;
|
||||
FixOffset = ThisByte + 1;
|
||||
Addendum += 1;
|
||||
break;
|
||||
case M68kBeads::Imm8:
|
||||
Size = 8;
|
||||
Pad = 8;
|
||||
FixOffset = ThisByte;
|
||||
break;
|
||||
case M68kBeads::Imm16:
|
||||
Size = 16;
|
||||
Pad = 0;
|
||||
FixOffset = ThisByte;
|
||||
break;
|
||||
case M68kBeads::Imm32:
|
||||
Size = 32;
|
||||
Pad = 0;
|
||||
FixOffset = ThisByte;
|
||||
break;
|
||||
case M68kBeads::Imm3:
|
||||
Size = 3;
|
||||
Pad = 0;
|
||||
NoExpr = true;
|
||||
break;
|
||||
}
|
||||
|
||||
LLVM_DEBUG(dbgs() << "\tEncodeImm"
|
||||
<< " Op: " << Op << ", Size: " << Size << ", Alt: " << Alt
|
||||
<< "\n");
|
||||
|
||||
MCOperand MCO;
|
||||
if (M68kII::hasMultiMIOperands(MI.getOpcode(), Op)) {
|
||||
|
||||
if (IsPCRel) {
|
||||
assert(!Alt && "You cannot use ALT operand with PCRel");
|
||||
MCO = MI.getOperand(MIOpIdx + M68k::PCRelDisp);
|
||||
} else {
|
||||
MCO = MI.getOperand(MIOpIdx + (Alt ? M68k::MemOuter : M68k::MemDisp));
|
||||
}
|
||||
|
||||
if (MCO.isExpr()) {
|
||||
assert(!NoExpr && "Cannot use expression here");
|
||||
const MCExpr *Expr = MCO.getExpr();
|
||||
|
||||
// This only makes sense for PCRel instructions since PC points to the
|
||||
// extension word and Disp8 for example is right justified and requires
|
||||
// correction. E.g. R_68K_PC32 is calculated as S + A - P, P for Disp8
|
||||
// will be EXTENSION_WORD + 1 thus we need to have A equal to 1 to
|
||||
// compensate.
|
||||
// TODO count extension words
|
||||
if (IsPCRel && Addendum != 0) {
|
||||
Expr = MCBinaryExpr::createAdd(
|
||||
Expr, MCConstantExpr::create(Addendum, Ctx), Ctx);
|
||||
}
|
||||
|
||||
Fixups.push_back(MCFixup::create(
|
||||
FixOffset, Expr, getFixupForSize(Size, IsPCRel), MI.getLoc()));
|
||||
// Write zeros
|
||||
return EmitConstant(0, Size, Pad, Buffer, Offset);
|
||||
}
|
||||
|
||||
} else {
|
||||
MCO = MI.getOperand(MIOpIdx);
|
||||
if (MCO.isExpr()) {
|
||||
assert(!NoExpr && "Cannot use expression here");
|
||||
const MCExpr *Expr = MCO.getExpr();
|
||||
|
||||
if (Addendum != 0) {
|
||||
Expr = MCBinaryExpr::createAdd(
|
||||
Expr, MCConstantExpr::create(Addendum, Ctx), Ctx);
|
||||
}
|
||||
|
||||
Fixups.push_back(MCFixup::create(
|
||||
FixOffset, Expr, getFixupForSize(Size, IsPCRel), MI.getLoc()));
|
||||
// Write zeros
|
||||
return EmitConstant(0, Size, Pad, Buffer, Offset);
|
||||
}
|
||||
}
|
||||
|
||||
int64_t I = MCO.getImm();
|
||||
|
||||
// Store 8 as 0, thus making range 1-8
|
||||
if (Type == M68kBeads::Imm3 && Alt) {
|
||||
assert(I && "Cannot encode Alt Imm3 zero value");
|
||||
I %= 8;
|
||||
} else {
|
||||
assert(isIntN(Size, I));
|
||||
}
|
||||
|
||||
uint64_t Imm = I;
|
||||
|
||||
// 32 bit Imm requires HI16 first then LO16
|
||||
if (Size == 32) {
|
||||
Offset += EmitConstant((Imm >> 16) & 0xFFFF, 16, Pad, Buffer, Offset);
|
||||
EmitConstant(Imm & 0xFFFF, 16, Pad, Buffer, Offset);
|
||||
return Size;
|
||||
}
|
||||
|
||||
return EmitConstant(Imm & ((1ULL << Size) - 1), Size, Pad, Buffer, Offset);
|
||||
}
|
||||
|
||||
#include "M68kGenMCCodeBeads.inc"
|
||||
|
||||
void M68kMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const {
|
||||
@@ -490,79 +230,16 @@ void M68kMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
|
||||
APInt EncodedInst(16, 0U);
|
||||
APInt Scratch(16, 0U);
|
||||
getBinaryCodeForInstr(MI, Fixups, EncodedInst, Scratch, STI);
|
||||
if (EncodedInst.getBitWidth()) {
|
||||
LLVM_DEBUG(dbgs() << "Instruction " << MCII.getName(Opcode) << "(" << Opcode
|
||||
<< ") is using the new code emitter\n");
|
||||
ArrayRef<uint64_t> Data(EncodedInst.getRawData(),
|
||||
EncodedInst.getNumWords());
|
||||
int64_t InstSize = EncodedInst.getBitWidth();
|
||||
for (uint64_t Word : Data) {
|
||||
for (int i = 0; i < 4 && InstSize > 0; ++i, InstSize -= 16) {
|
||||
support::endian::write<uint16_t>(OS, static_cast<uint16_t>(Word),
|
||||
support::big);
|
||||
Word >>= 16;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const uint8_t *Beads = getGenInstrBeads(MI);
|
||||
if (!Beads || !*Beads) {
|
||||
llvm_unreachable("*** Instruction does not have Beads defined");
|
||||
}
|
||||
|
||||
uint64_t Buffer = 0;
|
||||
unsigned Offset = 0;
|
||||
unsigned ThisByte = 0;
|
||||
|
||||
for (uint8_t Bead = *Beads; Bead; Bead = *++Beads) {
|
||||
// Check for control beads
|
||||
if (!(Bead & 0xF)) {
|
||||
switch (Bead >> 4) {
|
||||
case M68kBeads::Ignore:
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
switch (Bead & 0xF) {
|
||||
default:
|
||||
llvm_unreachable("Unknown Bead code");
|
||||
break;
|
||||
case M68kBeads::Bits1:
|
||||
case M68kBeads::Bits2:
|
||||
case M68kBeads::Bits3:
|
||||
case M68kBeads::Bits4:
|
||||
Offset +=
|
||||
encodeBits(ThisByte, Bead, MI, Desc, Buffer, Offset, Fixups, STI);
|
||||
break;
|
||||
case M68kBeads::DAReg:
|
||||
case M68kBeads::DA:
|
||||
case M68kBeads::DReg:
|
||||
case M68kBeads::Reg:
|
||||
Offset +=
|
||||
encodeReg(ThisByte, Bead, MI, Desc, Buffer, Offset, Fixups, STI);
|
||||
break;
|
||||
case M68kBeads::Disp8:
|
||||
case M68kBeads::Imm8:
|
||||
case M68kBeads::Imm16:
|
||||
case M68kBeads::Imm32:
|
||||
case M68kBeads::Imm3:
|
||||
Offset +=
|
||||
encodeImm(ThisByte, Bead, MI, Desc, Buffer, Offset, Fixups, STI);
|
||||
break;
|
||||
}
|
||||
|
||||
// Since M68k is Big Endian we need to rotate each instruction word
|
||||
while (Offset / 16) {
|
||||
support::endian::write<uint16_t>(OS, Buffer, support::big);
|
||||
Buffer >>= 16;
|
||||
Offset -= 16;
|
||||
ThisByte += 2;
|
||||
ArrayRef<uint64_t> Data(EncodedInst.getRawData(), EncodedInst.getNumWords());
|
||||
int64_t InstSize = EncodedInst.getBitWidth();
|
||||
for (uint64_t Word : Data) {
|
||||
for (int i = 0; i < 4 && InstSize > 0; ++i, InstSize -= 16) {
|
||||
support::endian::write<uint16_t>(OS, static_cast<uint16_t>(Word),
|
||||
support::big);
|
||||
Word >>= 16;
|
||||
}
|
||||
}
|
||||
|
||||
assert(Offset == 0 && "M68k Instructions are % 2 bytes");
|
||||
assert((ThisByte && !(ThisByte % 2)) && "M68k Instructions are % 2 bytes");
|
||||
}
|
||||
|
||||
MCCodeEmitter *llvm::createM68kMCCodeEmitter(const MCInstrInfo &MCII,
|
||||
|
||||
10
llvm/test/CodeGen/M68k/is-pcrel-register-operand-legal.mir
Normal file
10
llvm/test/CodeGen/M68k/is-pcrel-register-operand-legal.mir
Normal file
@@ -0,0 +1,10 @@
|
||||
# RUN: llc -O0 -mtriple=m68k -start-after=prologepilog -verify-machineinstrs %s -o - | FileCheck %s
|
||||
|
||||
name: is-pcrel-register-operand-legal
|
||||
body: |
|
||||
bb.0.entry:
|
||||
; CHECK: move.l (0,%pc,%a0), (%a1)
|
||||
; CHECK: move.l (%a0), (0,%pc,%a1)
|
||||
|
||||
MOV32jk $a1, 0, $a0, implicit-def $ccr
|
||||
MOV32kj 0, $a1, $a0, implicit-def $ccr
|
||||
@@ -8,7 +8,6 @@ add_tablegen(llvm-tblgen LLVM
|
||||
AsmWriterInst.cpp
|
||||
Attributes.cpp
|
||||
CallingConvEmitter.cpp
|
||||
CodeBeadsGen.cpp
|
||||
CodeEmitterGen.cpp
|
||||
CodeGenDAGPatterns.cpp
|
||||
CodeGenHwModes.cpp
|
||||
|
||||
@@ -1,135 +0,0 @@
|
||||
//===---------- CodeBeadsGen.cpp - Code Beads Generator -------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
// CodeBeads are data fields carrying auxiliary information for instructions.
|
||||
//
|
||||
// Under the hood it's simply implemented by a `bits` field (with arbitrary
|
||||
// length) in each TG instruction description, where this TG backend will
|
||||
// generate a helper function to access it.
|
||||
//
|
||||
// This is especially useful for expressing variable length encoding
|
||||
// instructions and complex addressing modes. Since in those cases each
|
||||
// instruction is usually associated with large amount of information like
|
||||
// addressing mode details used on a specific operand. Instead of retreating to
|
||||
// ad-hoc methods to figure out these information when encoding an instruction,
|
||||
// CodeBeads provide a clean table for the instruction encoder to lookup.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "CodeGenInstruction.h"
|
||||
#include "CodeGenTarget.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/TableGen/Error.h"
|
||||
#include "llvm/TableGen/Record.h"
|
||||
#include "llvm/TableGen/TableGenBackend.h"
|
||||
#include <vector>
|
||||
using namespace llvm;
|
||||
|
||||
namespace {
|
||||
|
||||
class CodeBeadsGen {
|
||||
RecordKeeper &Records;
|
||||
|
||||
public:
|
||||
CodeBeadsGen(RecordKeeper &R) : Records(R) {}
|
||||
void run(raw_ostream &OS);
|
||||
};
|
||||
|
||||
void CodeBeadsGen::run(raw_ostream &OS) {
|
||||
CodeGenTarget Target(Records);
|
||||
std::vector<Record *> Insts = Records.getAllDerivedDefinitions("Instruction");
|
||||
|
||||
// For little-endian instruction bit encodings, reverse the bit order
|
||||
Target.reverseBitsForLittleEndianEncoding();
|
||||
|
||||
ArrayRef<const CodeGenInstruction *> NumberedInstructions =
|
||||
Target.getInstructionsByEnumValue();
|
||||
|
||||
// Emit function declaration
|
||||
OS << "const uint8_t *llvm::" << Target.getInstNamespace();
|
||||
OS << "::getMCInstrBeads(unsigned Opcode) {\n";
|
||||
|
||||
// First, get the maximum bit length among all beads. And do some
|
||||
// simple validation
|
||||
unsigned MaxBitLength = 0;
|
||||
|
||||
for (const CodeGenInstruction *CGI : NumberedInstructions) {
|
||||
Record *R = CGI->TheDef;
|
||||
if (!R->getValue("Beads"))
|
||||
continue;
|
||||
|
||||
BitsInit *BI = R->getValueAsBitsInit("Beads");
|
||||
if (!BI->isComplete()) {
|
||||
PrintFatalError(R->getLoc(), "Record `" + R->getName() +
|
||||
"', bit field 'Beads' is not complete");
|
||||
}
|
||||
|
||||
MaxBitLength = std::max(MaxBitLength, BI->getNumBits());
|
||||
}
|
||||
|
||||
// Number of bytes
|
||||
unsigned Parts = MaxBitLength / 8;
|
||||
|
||||
// Emit instruction base values
|
||||
OS << " static const uint8_t InstBits[][" << Parts << "] = {\n";
|
||||
for (const CodeGenInstruction *CGI : NumberedInstructions) {
|
||||
Record *R = CGI->TheDef;
|
||||
|
||||
if (R->getValueAsString("Namespace") == "TargetOpcode" ||
|
||||
!R->getValue("Beads")) {
|
||||
OS << "\t{ 0x0 },\t// ";
|
||||
if (R->getValueAsBit("isPseudo"))
|
||||
OS << "(Pseudo) ";
|
||||
OS << R->getName() << "\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
BitsInit *BI = R->getValueAsBitsInit("Beads");
|
||||
|
||||
// Convert to byte array:
|
||||
// [dcba] -> [a][b][c][d]
|
||||
OS << "\t{";
|
||||
for (unsigned p = 0; p < Parts; ++p) {
|
||||
unsigned Right = 8 * p;
|
||||
unsigned Left = Right + 8;
|
||||
|
||||
uint8_t Value = 0;
|
||||
for (unsigned i = Right; i != Left; ++i) {
|
||||
unsigned Shift = i % 8;
|
||||
if (auto *B = dyn_cast<BitInit>(BI->getBit(i))) {
|
||||
Value |= (static_cast<uint8_t>(B->getValue()) << Shift);
|
||||
} else {
|
||||
PrintFatalError(R->getLoc(), "Record `" + R->getName() +
|
||||
"', bit 'Beads[" + Twine(i) +
|
||||
"]' is not defined");
|
||||
}
|
||||
}
|
||||
|
||||
if (p)
|
||||
OS << ',';
|
||||
OS << " 0x";
|
||||
OS.write_hex(Value);
|
||||
OS << "";
|
||||
}
|
||||
OS << " }," << '\t' << "// " << R->getName() << "\n";
|
||||
}
|
||||
OS << "\t{ 0x0 }\n };\n";
|
||||
|
||||
// Emit initial function code
|
||||
OS << " return InstBits[Opcode];\n"
|
||||
<< "}\n\n";
|
||||
}
|
||||
|
||||
} // End anonymous namespace
|
||||
|
||||
namespace llvm {
|
||||
|
||||
void EmitCodeBeads(RecordKeeper &RK, raw_ostream &OS) {
|
||||
emitSourceFileHeader("Machine Code Beads", OS);
|
||||
CodeBeadsGen(RK).run(OS);
|
||||
}
|
||||
|
||||
} // namespace llvm
|
||||
@@ -25,7 +25,6 @@ enum ActionType {
|
||||
NullBackend,
|
||||
DumpJSON,
|
||||
GenEmitter,
|
||||
GenCodeBeads,
|
||||
GenRegisterInfo,
|
||||
GenInstrInfo,
|
||||
GenInstrDocs,
|
||||
@@ -82,8 +81,6 @@ cl::opt<ActionType> Action(
|
||||
clEnumValN(DumpJSON, "dump-json",
|
||||
"Dump all records as machine-readable JSON"),
|
||||
clEnumValN(GenEmitter, "gen-emitter", "Generate machine code emitter"),
|
||||
clEnumValN(GenCodeBeads, "gen-code-beads",
|
||||
"Generate machine code beads"),
|
||||
clEnumValN(GenRegisterInfo, "gen-register-info",
|
||||
"Generate registers and register classes info"),
|
||||
clEnumValN(GenInstrInfo, "gen-instr-info",
|
||||
@@ -164,9 +161,6 @@ bool LLVMTableGenMain(raw_ostream &OS, RecordKeeper &Records) {
|
||||
case GenEmitter:
|
||||
EmitCodeEmitter(Records, OS);
|
||||
break;
|
||||
case GenCodeBeads:
|
||||
EmitCodeBeads(Records, OS);
|
||||
break;
|
||||
case GenRegisterInfo:
|
||||
EmitRegisterInfo(Records, OS);
|
||||
break;
|
||||
|
||||
@@ -67,7 +67,6 @@ void EmitAsmMatcher(RecordKeeper &RK, raw_ostream &OS);
|
||||
void EmitAsmWriter(RecordKeeper &RK, raw_ostream &OS);
|
||||
void EmitCallingConv(RecordKeeper &RK, raw_ostream &OS);
|
||||
void EmitCodeEmitter(RecordKeeper &RK, raw_ostream &OS);
|
||||
void EmitCodeBeads(RecordKeeper &RK, raw_ostream &OS);
|
||||
void EmitDAGISel(RecordKeeper &RK, raw_ostream &OS);
|
||||
void EmitDFAPacketizer(RecordKeeper &RK, raw_ostream &OS);
|
||||
void EmitDisassembler(RecordKeeper &RK, raw_ostream &OS);
|
||||
|
||||
Reference in New Issue
Block a user