Skip to content

Pointers from the host in the cross-compiled LLVM IR #759

@Alexander-Barth

Description

@Alexander-Barth

I am using GPUCompiler to cross-compile julia code for a RISC-V based microcontroller (ESP32 c3). The entry-points using the Arduino API are a setup() (for initialization) and a loop() function (to be run repeatedly). Here is an example in C++:

https://github.com/arduino/arduino-examples/blob/main/examples/01.Basics/Blink/Blink.ino

I would like to emulate this kind of API in julia.
Both functions do not have any arguments, therefore all shared information must be with global variables.

For all global variables, GPUCompiler uses the memory address of the host, for example:

module blinking_leds
using ESP32RISCVCompiler.Arduino

const counter = Ref{Int32}()

function setup()
    counter[] = 0
end

function loop()
end
end

This gets compiled into:

define i32 @_Z5setupv() local_unnamed_addr {                                                                                                                          
top:                                                                                                                                                                  
  store i32 0, ptr inttoptr (i32 -779740248 to ptr), align 4, !tbaa !2, !alias.scope !7, !noalias !10                                                                 
  ret i32 0                                                                                                                                                           
}

where -779740248 corresponds to Int32(pointer_from_objref(blinking_leds.counter)) on the host.
My current approach is to get a list of all module-global variables (using names(julia_module,all=true)), traverse the LLVM IR to remove all pointers matching module-global variables and to replace them by global variables declared in LLVM IR (https://codeberg.org/Alexander-Barth/ESP32RISCVCompiler/src/branch/main/src/global_references.jl#L103-L120).

Here is some initial discussion about this:
https://discourse.julialang.org/t/compiling-julia-code-for-a-risc-v-esp32-microcontroller/135108/3

I am wondering if there is a better way to do this?

A more complicated issue is the handling of string literals where I have also the problem that pointers from the host are present in the compiled binary. Unfortunately they are more difficult to handle as in the resulting LLVM IR there is no information left that this pointer represents a string:

function setup()
    a = "abc"
end

becomes:

define nonnull ptr @_Z5setupv() local_unnamed_addr {
top:
  ret ptr inttoptr (i32 -426048800 to ptr)
}

Maybe is it possible to use some LLVM metadata or to transform the code at a different level of the compilation pipeline?

I am well aware that an esp32 device is not exactly a GPU :-) Let me know if this should be rather a discussion post on discourse rather than an issue here.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions