
In the RISC-V architecture, multiple vendor-specific Control and Status Registers (CSRs) share the same encoding. However, the existing lookup function, which currently returns only a single result, falls short. During disassembly, it consistently returns the first CSR encountered, which may not be the correct CSR for the subtarget. To address this issue, we modify the function definition to return a range of results. These results can then be iterated upon to identify the CSR that best fits the subtarget’s feature requirements. The behavior of this new definition is controlled by a variable named `ReturnRange`, which defaults to `false`. Specifically, this patch introduces support for emitting a new lookup function for the primary key. This function returns a pair of iterators pointing to the first and last values, providing a comprehensive range of values that satisfy the query
66 lines
2.1 KiB
TableGen
66 lines
2.1 KiB
TableGen
// RUN: llvm-tblgen -gen-searchable-tables -I %p/../../include %s | FileCheck %s
|
|
|
|
include "llvm/TableGen/SearchableTable.td"
|
|
|
|
class SysReg<string name, bits<12> op> {
|
|
string Name = name;
|
|
bits<12> Encoding = op;
|
|
code FeaturesRequired = [{ {} }];
|
|
}
|
|
|
|
def List1 : GenericTable {
|
|
let FilterClass = "SysReg";
|
|
let Fields = [
|
|
"Name", "Encoding", "FeaturesRequired",
|
|
];
|
|
|
|
let PrimaryKey = [ "Encoding" ];
|
|
let PrimaryKeyName = "lookupSysRegByEncoding";
|
|
let PrimaryKeyReturnRange = true;
|
|
}
|
|
|
|
let FeaturesRequired = [{ {Feature1} }] in {
|
|
def : SysReg<"csr1", 0x7C0>;
|
|
}
|
|
|
|
let FeaturesRequired = [{ {Feature2} }] in {
|
|
def : SysReg<"csr2", 0x7C0>;
|
|
}
|
|
|
|
// CHECK: #ifdef GET_List1_DECL
|
|
// CHECK-NEXT: llvm::iterator_range<const SysReg *> lookupSysRegByEncoding(uint16_t Encoding);
|
|
// CHECK-NEXT: #endif
|
|
|
|
// CHECK: #ifdef GET_List1_IMPL
|
|
// CHECK-NEXT: constexpr SysReg List1[] = {
|
|
// CHECK-NEXT: { "csr1", 0x7C0, {Feature1} }, // 0
|
|
// CHECK-NEXT: { "csr2", 0x7C0, {Feature2} }, // 1
|
|
// CHECK-NEXT: };
|
|
|
|
// CHECK: llvm::iterator_range<const SysReg *> lookupSysRegByEncoding(uint16_t Encoding) {
|
|
// CHECK-NEXT: struct KeyType {
|
|
// CHECK-NEXT: uint16_t Encoding;
|
|
// CHECK-NEXT: };
|
|
// CHECK-NEXT: KeyType Key = {Encoding};
|
|
// CHECK-NEXT: struct Comp {
|
|
// CHECK-NEXT: bool operator()(const SysReg &LHS, const KeyType &RHS) const {
|
|
// CHECK-NEXT: if (LHS.Encoding < RHS.Encoding)
|
|
// CHECK-NEXT: return true;
|
|
// CHECK-NEXT: if (LHS.Encoding > RHS.Encoding)
|
|
// CHECK-NEXT: return false;
|
|
// CHECK-NEXT: return false;
|
|
// CHECK-NEXT: }
|
|
// CHECK-NEXT: bool operator()(const KeyType &LHS, const SysReg &RHS) const {
|
|
// CHECK-NEXT: if (LHS.Encoding < RHS.Encoding)
|
|
// CHECK-NEXT: return true;
|
|
// CHECK-NEXT: if (LHS.Encoding > RHS.Encoding)
|
|
// CHECK-NEXT: return false;
|
|
// CHECK-NEXT: return false;
|
|
// CHECK-NEXT: }
|
|
// CHECK-NEXT: };
|
|
// CHECK-NEXT: auto Table = ArrayRef(List1);
|
|
// CHECK-NEXT: auto It = std::equal_range(Table.begin(), Table.end(), Key, Comp());
|
|
// CHECK-NEXT: return llvm::make_range(It.first, It.second);
|
|
// CHECK-NEXT: }
|
|
// CHECK-NEXT: #endif
|