D on lm32-CPU: string argument on stack instead of register

Chad Joan chadjoan at gmail.com
Sat Aug 1 23:08:38 UTC 2020


On Saturday, 1 August 2020 at 08:58:03 UTC, Michael Reese wrote:
> [...]
> So the compiler knows how to use r1 and r2 for arguments. I 
> checked again in the lm32 manual 
> (https://www.latticesemi.com/view_document?document_id=52077), 
> and it says:
>
> "As illustrated in Table 3 on page 8, the first eight function 
> arguments are
> passed in registers. Any remaining arguments are passed on the 
> stack, as
> illustrated in Figure 12."
>
> So strings and structs should be passed on the stack and this 
> seems to be more an issue of the gcc lm32 backend than a D 
> issue.
>

Nice find!

Though if the compiler is allowed to split a single uint64_t into 
two registers, I would expect it to split struct/string into two 
registers as well. At least, the manual doesn't seem to 
explicitly mention higher-level constructs like structs. It does 
suggest a one-to-one relationship between arguments and registers 
(up to a point), but GCC seems to have decided otherwise for 
certain uint64_t's. (Looking at Table 3...) It even gives you two 
registers for a return value: enough for a string or an array. 
And if the backend/ABI weren't up for it, it would be 
theoretically possible to have the frontend to lower strings 
(dynamic arrays) and small structs into their components before 
function calls and then also insert code on the other side to 
cast them back into their original form. I'm not sure if anyone 
would want to write it, though. o.O

> But I just found a workaround using a wrapper function.
>
> void write_to_host(in string msg) {
>         write_to_hostC(msg.ptr, msg.length);
> }
>
> I checked the assembly code on the caller side, and the call 
> write_to host("Hello, World!\n") is inlined. There is only one 
> call to write_to_hostC. This is still not nice, but I think I 
> can live with that for now. Now I have to figure out how make 
> the cast back from from pointer-length pair into a string. I'm 
> sure I read that somewhere before, but forgot it and was unable 
> to find it now on a quick google search...

That's pretty clever. I like it.

Getting from pointer-length to string might be pretty easy:
string foo = ptr[0 .. len];

D allows pointers to be indexed, like in C. But unlike C, D has 
slices, and pointers can be "sliced". The result of a slice 
operation, at least for primitive arrays+pointers, is always an 
array (the "dynamic" ptr+length kind). Hope that helps.


> And since this is D: is there maybe some CTFE magic that allows 
> to create these wrappers automatically? Somthing like
>
> fix_stack!write_to_host("Hello, World!\n");
>

It ended up being a little more complicated than I thought it 
would be. Hope I didn't ruin the fun. ;)

https://pastebin.com/y6e9mxre


Also, that part where you mentioned a 64-bit integer being passed 
as a pair of registers made me start to wonder if unions could be 
(ab)used to juke the ABI:

https://pastebin.com/eGfZN0SL


>
>> Good luck with your lm32/FPGA coding. That sounds like cool 
>> stuff!
>
> I'm doing this mainly to improve my understanding of how 
> embedded processors work, and how to write linker scripts for a 
> given environment. Although I do have actual hardware where I 
> can see if everything runs in the real world, I mainly use 
> simulations. The coolest thing in my opinion is, nowadays it 
> can be done using only open source tools (mainly ghdl and 
> verilator, the lm32 source code is open source, too). The 
> complete system is simulated and you can look at every logic 
> signal in the cpu or in the ram while the program executes.

Thanks for the insights; I've done just a little hobby electrical 
stuff here-and-there, and having some frame of reference for tool 
and component choice makes me feel good, even if I don't plan on 
buying any lm32s or FPGAs anytime soon :)  Maybe I can Google 
some of that later and geek out at images of other people's 
debugging sessions or something. I'm curious how they manage the 
complexity that happens when circuits and massive swarms of logic 
gates do their, uh, complexity thing. o.O




More information about the Digitalmars-d-learn mailing list