This patch adds support in libunwind for rv32 hard flaot and soft-float for both rv32 and rv64.
Tried to generalise as much possible with lesser code duplication.
This doesn't seem correct.
If we go the generic route, why not just use unsigned long (or size_t, etc.) instead of these custom types? Also, these uncapitalized *_t names are generally typedefs, not preprocessor defines.
In the #else "branch" those variables aren't used, so presumably you still need those lines to avoid warnings about unused variables.
It might be a good idea to use instead __riscv_xlen == 32 || __riscv_xlen == 64, as that will correctly detect the case that riscv128 isn't handled.
If we are going to use a preprocessed instruction name (which I'm not sure we should) then at least the name should be ALL CAPS to make it obvious that it's a preprocessor definition, not a regular instruction.
ditto 32 || 64.
OK so it appears that in principle we could have 4 combinations
ILP32 + "f" : xlen = 32, flen = 32
So instead of having fixed size area for each kind of register thought of having packed size.
for all these below variants
ILP32 + "f" : xlen = 32, flen = 32 ===> 39
ILP32 + "fd" : xlen = 32, flen = 64 ===>55
LP64 + "f" : xlen = 64, flen = 32 ====>60
LP64 + "fd" : xlen = 64, flen = 64 ====>76 (was already done.)
That's the reason why libunwind is added as a blocking reviewer to reviews that touch libunwind. At least one maintainer (or person familiar with the code base) needs to give you a thumbs up.
Changes in these runtimes components have very wide impact, and unfortunately they're usually not very well tested. That's why we have these requirements.
I am not family with libunwind and don't know what's _LIBUNWIND_CURSOR_SIZE , but I am curious about does here different value for xlen=32/flen=and xlen=64/flen=0?
And I think add an #else + #error to catch any unsupported value would be better, since the flen could be 128 (Q), although LLVM didn't implement yet, but in case we implemented in future we'll know we need fix here.
You are right that _LIBUNWIND_CONTEXT_SIZE is correctly defined.
I see you changed uintX_t to be #defined as unsigned long. That was not the point of my previous comment. Is there an advantage in introducing these X types, instead of using existing types like, say, size_t?
Since you're going for a generic approach, and you already define things like RISCV_FOFFSET, instead of using #if #elses here I guess you could check that sizeof(_registers) == RISCV_FOFFSET*8, or something like that. If you keep this approach then it's probably best to to add an #else branch to error out for other conditions (e.g. riscv128).
I think you're right, everything here is generic so we don't need to error out here on unhandled cases, only in the code that sets the preprocessor definitions this code uses.
Isn't __riscv_xlen always defined when __riscv is defined? What's the point of this?
Better to put an #else branch here, to #error out on other cases (e.g. rv128).
Ditto #else, to #error out on other cases (e.g. quad-precision FP).
I have generated values for _LIBUNWIND_CURSOR_SIZE from UnwindCursor class size for each configration so that checkfit function becomes true.
static_assert((check_fit<UnwindCursor<A, R>, unw_cursor_t>::does_fit), "UnwindCursor<> does not fit in unw_cursor_t");
I tried to make sense of these values for commenting , but i could not.
@kamleshbhalui thanks for this, it looks to be shaping up well. I have only a couple of small comments first.
I think the purpose is that they want instances of UnwindCursor to be allocated on the stack, and it must fit within unw_cursor_t to do so.
As you have seen the calculation is: _UNWIND_CONTEXT_SIZE + (size of other UnwindCursor members / sizeof(uint64_t))
For the 64-bit ISA this comes out to _UNWIND_CONTEXT_SIZE + 12, and _UNWIND_CONTEXT_SIZE + 7 for 32-bit.
I don't think you need the extra parentheses in this statement.
Yep, I would also like to see this changed to a typedef before going in. Doing this as a define is very unusual.
Could you please indent the nested #ifs to improve readability?
Only the preprocessor directives need indentation, not the typedef.
I don't think size_t is an appropriate type for this, although it would likely work in all cases. I think what you want is either an unsigned long or something like the following:
#if __riscv_xlen == 64 typedef uint64_t reg_t; #elif __riscv_xlen == 32 typedef uint32_t reg_t; #endif
Hi, sorry for the delay in review. It would be helpful if you could go through the inline comments and mark them as "done" if they have been addressed. I see there are still a few comments that have been ignored.
This patch is tricky because there are no consistent indentation rules for preprocessor directives. In general, I think the indentation is only necessary for blocks where it increases readability (such as where _LIBUNWIND_CURSOR_SIZE is defined, or the block where reg_t is defined). Otherwise, it's best to follow the existing convention of the file.
Please look at this block again carefully. It should follow a rule of 1 space of indentation for each level of nesting.
Again, please fix these.
Everything inside this #if should have an additional space of indentation.
This is fine for now, but in the future, for such changes, please split this up into a series of patches. The clean ups for the named constants and clean up for floating point handling could have been separate changes which would have reduced the overall size of the changes and focused the patch specifically to adding support for rv32.