Skip to content

Adding RISCV to supported architectures #83

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: auto-sync
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions llvm/utils/TableGen/Printer.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/raw_ostream.h"

#include <regex>

typedef enum {
ST_NONE,
ST_DECL_OS,
Expand Down
103 changes: 91 additions & 12 deletions llvm/utils/TableGen/PrinterCapstone.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1112,11 +1112,11 @@ void PrinterCapstone::decoderEmitterEmitDecodeInstruction(
<< " /* Bogisity detected in disassembler state machine! */ \\\n"
<< "}\n\n";

std::set<std::string> InsnBytesAsUint16 = {"ARM", "TriCore", "ARC"};
std::set<std::string> InsnBytesAsUint16 = {"ARM", "TriCore", "ARC", "RISCV"};
std::set<std::string> InsnBytesAsUint24 = {"Xtensa"};
std::set<std::string> InsnBytesAsUint32 = {"ARM", "AArch64", "LoongArch",
"Alpha", "Mips", "TriCore",
"ARC", "Sparc"};
"ARC", "Sparc", "RISCV"};
std::set<std::string> InsnBytesAsUint64 = {"SystemZ", "ARC"};
bool MacroDefined = false;
if (InsnBytesAsUint16.find(TargetName) != InsnBytesAsUint16.end()) {
Expand Down Expand Up @@ -2983,6 +2983,15 @@ Record *argInitOpToRecord(Init *ArgInit) {
return Rec;
}

// diagram
// https://regexper.com/#OPERAND_%5BUS%5DIMM%5B0-9%5D%7B1%2C2%7D%28_%5BA-Z0-9%5D%2B%29*%7COPERAND_ZERO%7COPERAND_RVKRNUM%7COPERAND_VTYPEI%5B0-9%5D%7B1%2C2%7D%7COPERAND_UIMMLOG2XLEN%28_NONZERO%29%3F%7COPERAND_CLUI_IMM
static const std::regex RiscvImmOperandsPattern(
"OPERAND_[US]IMM[0-9]{1,2}(_[A-Z0-9]+)*" // e.g. OPERAND_UIMM12_NONZERO_BLAHBLAH42
"|" "OPERAND_ZERO" "|" "OPERAND_RVKRNUM"
"|" "OPERAND_VTYPEI[0-9]{1,2}" // e.g. OPERAND_VTYPEI10
"|" "OPERAND_UIMMLOG2XLEN(_NONZERO)?"
"|" "OPERAND_CLUI_IMM");

std::string getPrimaryCSOperandType(Record const *OpRec) {
std::string OperandType;
if (OpRec->isSubClassOf("PredicateOperand"))
Expand Down Expand Up @@ -3026,6 +3035,10 @@ std::string getPrimaryCSOperandType(Record const *OpRec) {
return "CS_OP_REG";
else if (OperandType == "OPERAND_NM_GPREL21")
return "CS_OP_REG";
// RISCV (keep this as the last check because it matches a lot of strings,
// so it might shadow another architecture's operand names if it's moved up)
else if (std::regex_match(OperandType, RiscvImmOperandsPattern))
return "CS_OP_IMM";
else if (OperandType == "OPERAND_NM_SAVE_REGLIST")
return "CS_OP_INVALID";
else
Expand Down Expand Up @@ -4081,6 +4094,8 @@ std::string getTableNamespacePrefix(const GenericTable &Table,
NSTable = &ARMNSTypePairs;
else if (StringRef(TargetName).upper() == "SPARC")
NSTable = &SparcNSTypePairs;
else if (StringRef(TargetName).upper() == "RISCV")
return "RISCV_"; // don't bother with a table
else
PrintFatalNote("No Namespace Type table defined for target.");

Expand Down Expand Up @@ -4166,9 +4181,70 @@ void PrinterCapstone::searchableTablesEmitIfFieldCase(
void PrinterCapstone::searchableTablesEmitKeyTypeStruct(
const GenericTable &Table, const SearchIndex &Index) const {}

uint64_t BitsInitToUInt(const BitsInit *BI) {
uint64_t Value = 0;
for (unsigned I = 0, Ie = BI->getNumBits(); I != Ie; ++I) {
if (BitInit *B = dyn_cast<BitInit>(BI->getBit(I)))
Value |= (uint64_t)B->getValue() << I;
}
return Value;
}

void PrinterCapstone::searchableTablesEmitKeyArray(const GenericTable &Table,
const SearchIndex &Index,
bool IsPrimary) const {}
bool IsPrimary) const {
if (!IsPrimary)
return;
if (Index.Fields.size() != 1)
return;

GenericField IndexField = Index.Fields[0];
if (IndexField.RecType == nullptr)
return;

RecTy::RecTyKind Kind = IndexField.RecType->getRecTyKind();
// only numerical or string fields are searchable
if (Kind != RecTy::BitRecTyKind && Kind != RecTy::BitsRecTyKind
&& Kind != RecTy::IntRecTyKind && Kind != RecTy::StringRecTyKind)
return;

raw_string_ostream &OS = searchableTablesGetOS(ST_IMPL_OS);
OS << "static const struct ";

bool IsNumericIndex = Kind != RecTy::StringRecTyKind;
// which struct to emit to represent the index type ?
if (IsNumericIndex)
OS << "IndexType";
else
OS << "IndexTypeStr";

ListSeparator LS;
OS << " Index[] = {\n" << LS;

int64_t idx = 0;
for (auto & entry : Table.Entries) {
OS << "{";
switch (Kind) {
case RecTy::BitRecTyKind:
OS << ((entry->getValueAsBit(IndexField.Name))? "true" : "false");
break;
case RecTy::BitsRecTyKind:
OS << BitsInitToUInt(entry->getValueAsBitsInit(IndexField.Name));
break;
case RecTy::IntRecTyKind:
OS << entry->getValueAsInt(IndexField.Name);
break;
case RecTy::StringRecTyKind:
OS << entry->getValueAsString(IndexField.Name);
break;
default:
llvm_unreachable("Kind of Index MUST be Bit, Bits, Int, or String");
}
OS << "," << idx << "}" << LS << "\n";
idx++;
}
OS << "};\n";
}

void PrinterCapstone::searchableTablesEmitIndexLamda(
const SearchIndex &Index, StringRef const &IndexName,
Expand Down Expand Up @@ -4211,14 +4287,6 @@ void PrinterCapstone::searchableTablesEmitMapII() const {
OutS << " { ";
}

uint64_t BitsInitToUInt(const BitsInit *BI) {
uint64_t Value = 0;
for (unsigned I = 0, Ie = BI->getNumBits(); I != Ie; ++I) {
if (BitInit *B = dyn_cast<BitInit>(BI->getBit(I)))
Value |= (uint64_t)B->getValue() << I;
}
return Value;
}

unsigned getEnumValue(Record *Entry) {
if (!Entry->getValue("EnumValueField") ||
Expand All @@ -4228,8 +4296,19 @@ unsigned getEnumValue(Record *Entry) {
BitsInit *BI = Entry->getValueAsBitsInit("Encoding");
return BitsInitToUInt(BI);
}
// RISCV fields
if (Entry->getValue("Inst")) {
BitsInit *BI = Entry->getValueAsBitsInit("Inst");
return BitsInitToUInt(BI);
}
if (Entry->getValue("Value")) {
BitsInit *BI = Entry->getValueAsBitsInit("Value");
return BitsInitToUInt(BI);
}
PrintWarning("Couldn't find an enum value for the following entry, returning a dummy 0 value");
Entry->dump();
PrintFatalNote("Which of those fields above are the encoding/enum value?");
PrintWarning("Which of those fields above are the encoding/enum value?");
return 0;
}
StringRef EnumValField = Entry->getValueAsString("EnumValueField");
return BitsInitToUInt(Entry->getValueAsBitsInit(EnumValField));
Expand Down
7 changes: 7 additions & 0 deletions llvm/utils/TableGen/SearchableTableEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,9 @@ void SearchableTableEmitter::run() {
}

for (auto *TableRec : Records.getAllDerivedDefinitions("GenericTable")) {
if (TableRec->getName().str() == "RISCVVIntrinsicsTable")
continue; // special case because this table has invalid characters that always fails compilation

auto Table = std::make_unique<GenericTable>();
Table->Name = std::string(TableRec->getName());
Table->Locs = TableRec->getLoc();
Expand Down Expand Up @@ -637,6 +640,10 @@ void EmitSearchableTables(RecordKeeper &RK, raw_ostream &OS) {
// Sparc's lowest class is InstSP not I
IDef = RK.getClass("InstSP");
}
if (!IDef) {
// try RISCV's root class which is RVInstCommon not I
IDef = RK.getClass("RVInstCommon");
}
if (!IDef) {
// If this is reached we need to implement the search for other classes which have Namespace set.
llvm_unreachable("Root instruction class \"I\" does not exist for this target.");
Expand Down