I'm trying to hack the Clang/LLVM compiler to do work around a specific RISC-V hardware issue on the processor I am working on.
It appears that loading addresses that are not 16/32-bit aligned does not work as expected. To work around this, I'd like to modify the compiler to change all lb/lbu
and sb
instructions to instead work on a full word or dword.
For example, I have the following struct:
union Flags
{
struct
{
uint32_t enabled : 1;
uint32_t reserved : 7;
uint32_t foo : 1;
uint32_t reserved2 : 23;
};
uint32_t u32All;
};
Right now, when the compiled program tries to access a pointer containing Flags->foo
, it does so with an lbu
instruction that is at address X+1(byte). This offset is truncated by the hardware and so it reads the address X instead, which would return the enabled
flag instead of the foo
flag.
I need to promote the load into a word/dword and then operate on it properly.
I'm not knowledgeable about LLVM in the slightest. I've tried poking around RISCVISelLowering.cpp, but the only thing I've managed to do is cause lld
to crash when it attempts to legalize the load ops.
Looking for any help or guidance you might be able to provide. Thank you!