hey, i'm working on a bare-metal x86_64 kernel using tinygo and i'm currently implementing the limine boot protocol which needs requests to be placed in a specific section so that it can find them. i'm currently doing this with the //go:section directive:
//go:section .limine_requests
var FramebufferRequest = LimineFramebufferRequest{
Id: LIMINE_FRAMEBUFFER_REQUEST_ID,
Revision: 0,
}
this works as expected before optimization. for example, with -opt=0, the LLVM IR contains:
@"fey/kernel/limine/framebuffer.FramebufferRequest" = internal global ..., section ".limine_requests"
however, with -opt=1, -opt=2, -opt=s, or -opt=z, the global gets completely removed because nothing in the Go program references it.
i can confirm that it's actually being removed rather than just moved to another section. searching the generated LLVM IR at -opt=1 only finds the DWARF debug information for the variable:
!DIGlobalVariable(name: "fey/kernel/limine/framebuffer.FramebufferRequest", ...)
there is no actual LLVM global and no .limine_requests section.
this is a problem for things like limine requests because the variable is intentionally not referenced by the program. its purpose is to exist in the final .elf so that something outside the Go program, in this case the bootloader, can find it.
i don't think //go:section should necessarily imply that a global is used, but it would be useful to have some way to explicitly tell TinyGo that a global must not be dead-stripped.
for example, something like:
which could cause tinygo to retain the global through LLVM's llvm.used / llvm.compiler.used mechanisms.
i couldn't find an existing tinygo directive for this, so is there currently an intended way to prevent a global from being stripped, or would adding a directive for this be something the maintainers would consider?
thank you!
hey, i'm working on a bare-metal x86_64 kernel using tinygo and i'm currently implementing the limine boot protocol which needs requests to be placed in a specific section so that it can find them. i'm currently doing this with the
//go:sectiondirective:this works as expected before optimization. for example, with
-opt=0, the LLVM IR contains:however, with
-opt=1,-opt=2,-opt=s, or-opt=z, the global gets completely removed because nothing in the Go program references it.i can confirm that it's actually being removed rather than just moved to another section. searching the generated LLVM IR at
-opt=1only finds the DWARF debug information for the variable:there is no actual LLVM global and no
.limine_requestssection.this is a problem for things like limine requests because the variable is intentionally not referenced by the program. its purpose is to exist in the final .elf so that something outside the Go program, in this case the bootloader, can find it.
i don't think
//go:sectionshould necessarily imply that a global is used, but it would be useful to have some way to explicitly tell TinyGo that a global must not be dead-stripped.for example, something like:
which could cause tinygo to retain the global through LLVM's
llvm.used/llvm.compiler.usedmechanisms.i couldn't find an existing tinygo directive for this, so is there currently an intended way to prevent a global from being stripped, or would adding a directive for this be something the maintainers would consider?
thank you!