В качестве упражнения для оценки гибкости LLVM и RISC-V для поддержки разработки процессоров по обычному заказу я попытался добавить векторный регистровый файл в порт LowRISC RISCV LLVM. Я могу получить простую инструкцию добавления вектора для компиляции из ассемблера. Тем не менее, когда я пытаюсь выполнить тест туда и обратно (ассемблер + дизассемблер), llvm-objdump вылетает с исключением при попытке разобрать операнды инструкции vadd.
Вывод llvm-objdump:
> ./bin/llvm-mc rv32v-valid.s -triple=riscv32 -mattr=+m -filetype=obj |
> ./bin/llvm-objdump -mattr=+m -riscv-no-aliases -d -
>
> <stdin>: file format ELF32-riscv
>
> Disassembly of section .text: .text:
> 0: 0b 80 20 02 vadd llvm-objdump: /srv/workspaces/smutz/llvm-riscv/llvm/include/llvm/ADT/SmallVector.h:154:
> const_reference llvm::SmallVectorTemplateCommon<llvm::MCOperand,
> void>::operator[](size_type) const [T = llvm::MCOperand]: Assertion
> `idx < size()' failed.
> #0 0x00007f9c85945d4c llvm::sys::PrintStackTrace(llvm::raw_ostream&) /srv/workspaces/smutz/llvm-riscv/llvm/lib/Support/Unix/Signals.inc:398:0
> #1 0x00007f9c85945ef9 PrintStackTraceSignalHandler(void*) /srv/workspaces/smutz/llvm-riscv/llvm/lib/Support/Unix/Signals.inc:462:0
> #2 0x00007f9c85944433 llvm::sys::RunSignalHandlers() /srv/workspaces/smutz/llvm-riscv/llvm/lib/Support/Signals.cpp:50:0
> #3 0x00007f9c8594658f SignalHandler(int) /srv/workspaces/smutz/llvm-riscv/llvm/lib/Support/Unix/Signals.inc:252:0
> #4 0x00007f9c852ac330 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x10330)
> #5 0x00007f9c846e9c37 gsignal /build/eglibc-ripdx6/eglibc-2.19/signal/../nptl/sysdeps/unix/sysv/linux/raise.c:56:0
> #6 0x00007f9c846ed028 abort /build/eglibc-ripdx6/eglibc-2.19/stdlib/abort.c:91:0
> #7 0x00007f9c846e2bf6 __assert_fail_base /build/eglibc-ripdx6/eglibc-2.19/assert/assert.c:92:0
> #8 0x00007f9c846e2ca2 (/lib/x86_64-linux-gnu/libc.so.6+0x2fca2)
> #9 0x00007f9c88ea84c1 llvm::SmallVectorTemplateCommon<llvm::MCOperand, void>::operator[](unsigned long) const
> /srv/workspaces/smutz/llvm-riscv/llvm/include/llvm/ADT/SmallVector.h:155:0
> #10 0x00007f9c88ea84c1 llvm::MCInst::getOperand(unsigned int) const /srv/workspaces/smutz/llvm-riscv/llvm/include/llvm/MC/MCInst.h:180:0
> #11 0x00007f9c88ea0208 llvm::RISCVInstPrinter::printOperand(llvm::MCInst const*, unsigned
> int, llvm::MCSubtargetInfo const&, llvm::raw_ostream&, char const*)
> /srv/workspaces/smutz/llvm-riscv/llvm/lib/Target/RISCV/InstPrinter/RISCVInstPrinter.cpp:54:0
> #12 0x00007f9c88e9fd4c llvm::RISCVInstPrinter::printInstruction(llvm::MCInst const*,
> llvm::MCSubtargetInfo const&, llvm::raw_ostream&)
> /srv/workspaces/smutz/llvm-riscv/build/lib/Target/RISCV/RISCVGenAsmWriter.inc:1089:0
> #13 0x00007f9c88ea7ef7 llvm::RISCVInstPrinter::printInst(llvm::MCInst const*, llvm::raw_ostream&, llvm::StringRef, llvm::MCSubtargetInfo
> const&)
> /srv/workspaces/smutz/llvm-riscv/llvm/lib/Target/RISCV/InstPrinter/RISCVInstPrinter.cpp:43:0
> #14 0x0000000000420c14 (anonymous namespace)::PrettyPrinter::printInst(llvm::MCInstPrinter&,
> llvm::MCInst const*, llvm::ArrayRef<unsigned char>, unsigned long,
> llvm::raw_ostream&, llvm::StringRef, llvm::MCSubtargetInfo const&,
> (anonymous namespace)::SourcePrinter*)
> /srv/workspaces/smutz/llvm-riscv/llvm/tools/llvm-objdump/llvm-objdump.cpp:514:0
> #15 0x0000000000425125 DisassembleObject(llvm::object::ObjectFile const*, bool)
> /srv/workspaces/smutz/llvm-riscv/llvm/tools/llvm-objdump/llvm-objdump.cpp:1604:0
> #16 0x000000000042126c DumpObject(llvm::object::ObjectFile*, llvm::object::Archive const*)
> /srv/workspaces/smutz/llvm-riscv/llvm/tools/llvm-objdump/llvm-objdump.cpp:2055:0
> #17 0x0000000000420893 DumpInput(llvm::StringRef) /srv/workspaces/smutz/llvm-riscv/llvm/tools/llvm-objdump/llvm-objdump.cpp:2146:0
> #18 0x0000000000433122 void (*std::for_each<__gnu_cxx::__normal_iterator<std::string*,
> std::vector<std::string, std::allocator<std::string> > >, void
> (*)(llvm::StringRef)>(__gnu_cxx::__normal_iterator<std::string*,
> std::vector<std::string, std::allocator<std::string> > >,
> __gnu_cxx::__normal_iterator<std::string*, std::vector<std::string, std::allocator<std::string> > >, void
> (*)(llvm::StringRef)))(llvm::StringRef)
> /usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/stl_algo.h:4417:0
> #19 0x000000000043304b void (*llvm::for_each<llvm::cl::list<std::string, bool,
> llvm::cl::parser<std::string> >&, void
> (*)(llvm::StringRef)>(llvm::cl::list<std::string, bool,
> llvm::cl::parser<std::string> >&, void
> (*)(llvm::StringRef)))(llvm::StringRef)
> /srv/workspaces/smutz/llvm-riscv/llvm/include/llvm/ADT/STLExtras.h:808:0
> #20 0x0000000000420732 main /srv/workspaces/smutz/llvm-riscv/llvm/tools/llvm-objdump/llvm-objdump.cpp:2208:0
> #21 0x00007f9c846d4f45 __libc_start_main /build/eglibc-ripdx6/eglibc-2.19/csu/libc-start.c:321:0
> #22 0x000000000041cb2e _start (./bin/llvm-objdump+0x41cb2e) Stack dump:
> 0. Program arguments: ./bin/llvm-objdump -mattr=+m -riscv-no-aliases -d - Aborted
Биты, которые я добавил для поддержки вектора:
In lib/Target/RISCV/RISCVRegisterInfo.td
// Vector registers
let RegAltNameIndices = [ABIRegAltName] in {
def V0 : RISCVReg<0, "v0", ["v0"]>, DwarfRegNum<[64]>;
def V1 : RISCVReg<1, "v1", ["v1"]>, DwarfRegNum<[65]>;
def V2 : RISCVReg<2, "v2", ["v2"]>, DwarfRegNum<[66]>;
def V3 : RISCVReg<3, "v3", ["v3"]>, DwarfRegNum<[67]>;
def V4 : RISCVReg<4, "v4", ["v4"]>, DwarfRegNum<[68]>;
def V5 : RISCVReg<5, "v5", ["v5"]>, DwarfRegNum<[69]>;
def V6 : RISCVReg<6, "v6", ["v6"]>, DwarfRegNum<[70]>;
def V7 : RISCVReg<7, "v7", ["v7"]>, DwarfRegNum<[71]>;
def V8 : RISCVReg<8, "v8", ["v8"]>, DwarfRegNum<[72]>;
def V9 : RISCVReg<9, "v9", ["v9"]>, DwarfRegNum<[73]>;
def V10 : RISCVReg<10,"v10", ["v10"]>, DwarfRegNum<[74]>;
def V11 : RISCVReg<11,"v11", ["v11"]>, DwarfRegNum<[75]>;
def V12 : RISCVReg<12,"v12", ["v12"]>, DwarfRegNum<[76]>;
def V13 : RISCVReg<13,"v13", ["v13"]>, DwarfRegNum<[77]>;
def V14 : RISCVReg<14,"v14", ["v14"]>, DwarfRegNum<[76]>;
def V15 : RISCVReg<15,"v15", ["v15"]>, DwarfRegNum<[79]>;
def V16 : RISCVReg<16, "v16", ["v16"]>, DwarfRegNum<[80]>;
def V17 : RISCVReg<17, "v17", ["v17"]>, DwarfRegNum<[81]>;
def V18 : RISCVReg<18, "v18", ["v18"]>, DwarfRegNum<[82]>;
def V19 : RISCVReg<19, "v19", ["v19"]>, DwarfRegNum<[83]>;
def V20 : RISCVReg<20, "v20", ["v20"]>, DwarfRegNum<[84]>;
def V21 : RISCVReg<21, "v21", ["v21"]>, DwarfRegNum<[85]>;
def V22 : RISCVReg<22, "v22", ["v22"]>, DwarfRegNum<[86]>;
def V23 : RISCVReg<23, "v23", ["v23"]>, DwarfRegNum<[87]>;
def V24 : RISCVReg<24, "v24", ["v24"]>, DwarfRegNum<[88]>;
def V25 : RISCVReg<25, "v25", ["v25"]>, DwarfRegNum<[89]>;
def V26 : RISCVReg<26, "v26", ["v26"]>, DwarfRegNum<[90]>;
def V27 : RISCVReg<27, "v27", ["v27"]>, DwarfRegNum<[91]>;
def V28 : RISCVReg<28, "v28", ["v28"]>, DwarfRegNum<[92]>;
def V29 : RISCVReg<29, "v29", ["v29"]>, DwarfRegNum<[93]>;
def V30 : RISCVReg<30, "v30", ["v30"]>, DwarfRegNum<[94]>;
def V31 : RISCVReg<31, "v31", ["v31"]>, DwarfRegNum<[95]>;
}
// The order of registers represents the preferred allocation sequence,
// meaning caller-save regs are listed before callee-save.
def VR : RegisterClass<"RISCV", [v8i32], 256, (add
(sequence "V%u", 0, 31)
)>;
И
In lib/Target/RISCV/RISCVRegisterInfo.td
def OPC_OP_V : RISCVOpcode<0b0001011>;
let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
class V_rr<bits<7> funct7, bits<3> funct3, string opcodestr>
: RVInstR<funct7, funct3, OPC_OP_V, (outs VR:$vd), (ins VR:$v1, VR:$v2),
opcodestr, "$vd, $v1, $v2">;
def VADD : V_rr<0b0000001, 0b000, "vadd">;
Когда я смотрю на код для RISCV, в lib / Target / RISCV / Disassembler / RISCVDisassembler.cpp объявлена функция, называемая DecodeGPRRegisterClass () и аналогичная для регистров FPR, которые, похоже, играют роль в разборке. Эти функции вызываются из кода, сгенерированного TableGen. Я добавил функцию для моего нового класса векторных регистров. Однако к нему не генерируются вызовы, что не соответствует ожиданиям.
Я посмотрел вокруг и просмотрел патчи, используемые для реализации поддержки RISCV, но я пока не смог понять, что я упустил, чтобы заставить дизассемблер работать с новыми классами регистров. Я был бы очень признателен за некоторые советы.