Using p2llvm
David Betz
Posts: 14,516
in C/C++
I thought I would remove my questions about using p2llvm from the thread addressing upstreaming the p2llvm source code.
I got a simple "Hello, world" program working and now I'm trying to compile my xlisp interpreter. It looks like my first problem is that setjmp/longjmp are not supported by p2llvm. Would it be relatively easy to add them?
dbetz@Davids-Mini-2 xlisp % make TARGET=p2llvm /opt/p2llvm/bin/clang -fno-exceptions --target=p2 -Dprintf=__simple_printf -Wall -DUNIX -Iinclude -c src/xlapi.c -o obj/lib/xlapi.o src/xlapi.c:39:16: warning: incompatible pointer types passing 'jmp_buf' (aka 'unsigned long [9]') to parameter of type 'void **' [-Wincompatible-pointer-types] if (setjmp(target.target) != 0) { ^~~~~~~~~~~~~ src/xlapi.c:39:9: error: __builtin_setjmp is not supported for the current target if (setjmp(target.target) != 0) { ^~~~~~~~~~~~~~~~~~~~~ /opt/p2llvm/bin/../libc/include/setjmp.h:16:16: note: expanded from macro 'setjmp' #define setjmp __builtin_setjmp
Comments
As a followup to my previous message, have you defined the ABI for p2llvm somewhere? To write setjmp/longjmp it is necessary to understand what registers need to be saved by setjmp so longjmp can restore them to the correct state.
Regarding setjmp/longjmp, I'm not super familiar with what those do as I've never used them, but my understanding is it's a C library thing, not strictly a compiler level thing, right? The C library needs some love for sure, but I'm guessing it shouldn't be too hard to add. However if it's a builtin, then maybe it needs to go into libp2. In either case, shouldn't be hard if I understand the functionality correctly. Is that something you would want to take a stab at?
Regarding an ABI, I don't have a formal document, but it's on the list. However, most of the necessary info should be in the various docs I've written here: https://github.com/ne75/p2llvm/tree/master/docs. Maybe today I'll start the actual ABI, cause that could unlock other people to make improvements to the C library/P2 library and fix things like this.
I'll take a look at your document. I don't really need a formal ABI document. I just need to know what registers have to be preserved.
Cool. In theory, it should just be r0-r31 and ptra, if I understand how setjmp works correctly.
@n_ermosh Can you point me to some assembly code in the p2llvm project? I will try writing setjmp/longjmp but I'd like to see some assembly code that works with the p2llvm runtime library.
Here's a basic one that is implementing left shift as a light example: https://github.com/ne75/p2llvm/blob/master/libp2/lib/builtins/ashldi3.c
Here's an example of inline assembly, mixing C and asm: https://github.com/ne75/p2llvm/blob/master/libp2/lib/propeller2.c#L27-L37
Here's my debugger program that's much larger: https://github.com/ne75/p2llvm/blob/master/libp2/lib/p2db/p2db.c
Also for reference, this is where all instructions are defined: https://github.com/ne75/llvm-project/blob/edea2b509def0b02fd3f291ca0af6a9244158d52/llvm/lib/Target/P2/P2InstrInfo.td. It's not a clean list, but if you search for a specific mnemonic, if it's not there, then it's not yet implemented.
Thanks!!
I'm trying to understand the code that is generated by p2llvm. I wrote this function:
It compiled to this:
What are the locations #353, #319, and #351 used for? I thought at first they were just the absolute addresses of registers but r0 starts at $1d3=464 according to the docs. What are #353, #319, and #351 used for?
Those are the “special immediates” that’s cause rd/wrlong to operate on PTRA, I just don’t have them print out as a nice ptra expression. See pages 66-68 of the silicon docs.
The generated code you posted does the following (and looks to be correct):
I’m guessing you didn’t enable optimization when compiling, so the code will be relatively inefficient.
Correct. I didn't use any optimization. Thanks for your description.