Hi all, I am trying to select a certain register I added to RISCV for a store instruction. How can I do that and which files should I edit? Will I necessarily have to look into SelectionDAG or is it possible without getting into it?
Register classes are defined in RISCVRegisterInfo.td and used by RISCVInstrInfo*.td. Whether you need to touch C++ code or can stay in TableGen land depends on what exactly you’re trying to do.
Suppose I compile this simple C code-
#include<stdio.h>
int main()
{
int a = 7;
return a;
}
When I look at the disassembly of the object code, for sw instruction I want a register xy to show up. Instead it shows s0 in the disassembly eg. at line starting with 101de. I think I have been able to add the register by editing RISCVRegisterInfo.td but want the sw instruction to only work with xy.
00000000000101d4 <main>:
101d4: 01 11 addi sp, sp, -32
101d6: 06 ec sd ra, 24(sp)
101d8: 22 e8 sd s0, 16(sp)
101da: 00 10 addi s0, sp, 32
101dc: 01 46 li a2, 0
101de: 23 26 c4 fe sw a2, -20(s0)
101e2: 1d 46 li a2, 7
101e4: 23 24 c4 fe sw a2, -24(s0)
101e8: 03 25 84 fe lw a0, -24(s0)
101ec: e2 60 ld ra, 24(sp)
101ee: 42 64 ld s0, 16(sp)
101f0: 05 61 addi sp, sp, 32
101f2: 82 80 ret
You’re going to need to be more specific than that. Also I don’t know how you expect to encode that when all 32 values for the 5-bit rs1 field are taken by the existing x0-x31 general-purpose integer registers.
I was able to figure it out, it was a silly mistake, I was using the wrong disassembler instead of the llvm’s disassembler. I am able to use my added register. Will try to be more specific from next time.
To give you more context regarding my problem we are working on adding a custom 16 bit register to RISCV and we need a new type to be added which only stores or loads from that particular register. Right now I am still playing around, (making changes and seeing what works whether it actually makes sense or not). So I changed the RISCVReg encoding to use my added register instead of one particular GPR.
After this I changed the sw instruction to use my XYreg register class. This way I am able to compile the above and use XY register for sw instructions. I realize this is an incorrect way to do this and I am looking for guidance on how I should approach my problem. I was thinking as a next step to add a new type for my added register so that XY a = 7;
in C code would load and store from my particular register.
We have a bunch of code in C already written this way that is being compiled using a proprietary compiler, so finally what I want is the compilation process from C to object code to work for this line XY a = 7;
using changes I do to LLVM and not use the proprietary compiler at all.
Additionally, I added a new derived type for that register in LLVM using the extending LLVM tutorial https://llvm.org/docs/ExtendingLLVM.html for adding a new derived type following code already present for int type. I was hoping this would at least compile XY a = 7;
but I am assuming I would also require changes to clang? If anyone could help me answer this question or could provide general guidance I would be extremely grateful.
Thank you.
I don’t understand why you would need a new type to add a 16-bit register. What problem are you trying to solve?
I’m trying to simulate a different proprietary compiler in a way using LLVM.
The new type is to reuse the already written C code we have which has lines like
XY xy_in;
int temp1 = 7;
xy_in = *(XY*)&(temp1);
The current proprietary compiler we were using compiles this into loading into a specific register XY. The C code makes it look really similar to a type, so I thought adding XY as a type might be a good idea.
The disassembly of the compiled code has load and store instructions that load and store into the xy instruction and I want to simulate that with llvm. Please let me know if I can provide more clarification.
How else could I use my added register directly through C code? Will changes be needed to be made to clang? Or is this a very unusual task?
C doesn’t expose registers. Every variable is conceptually in memory, and a type doesn’t change that. What is the purpose of this register? Do you want something that acts like memory mapped / volatile reads of this register? Is it used separately from the program? The closest thing we probably have is the read_register/write_register intrinsic, but those are not very useful depending on the context.