-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Strongly typed code generation specs #14090
Comments
Also this would work with 128-bit integers: crystal/spec/compiler/codegen/primitives_spec.cr Lines 17 to 25 in 8fe3c70
(to be fair most specs in that file should be moved to |
And also OrcV2 LLJIT (#14856) doesn't have an |
OrcV2 supposedly supports linking to symbols in the current process (apparently this is necessary for even EDIT: Trying to forcibly disable emulated TLS: void LLVMExtDisableEmulatedTLS(LLVMOrcJITTargetMachineBuilderRef Builder) {
auto *JTMB = reinterpret_cast<orc::JITTargetMachineBuilder *>(Builder);
JTMB->getOptions().EmulatedTLS = false;
} lib LibLLVM
alias OrcJITTargetMachineBuilderRef = Void*
fun orc_jit_target_machine_builder_detect_host = LLVMOrcJITTargetMachineBuilderDetectHost(result : OrcJITTargetMachineBuilderRef*) : ErrorRef
fun orc_lljit_builder_set_jit_target_machine_builder = LLVMOrcLLJITBuilderSetJITTargetMachineBuilder(builder : OrcLLJITBuilderRef, jtmb : OrcJITTargetMachineBuilderRef)
end
lib LibLLVMExt
fun disable_emulated_tls = LLVMExtDisableEmulatedTLS(LibLLVM::OrcJITTargetMachineBuilderRef)
end
lljit_builder = LLVM::Orc::LLJITBuilder.new
LLVM.assert LibLLVM.orc_jit_target_machine_builder_detect_host(out jtmb)
LibLLVMExt.disable_emulated_tls(jtmb)
LibLLVM.orc_lljit_builder_set_jit_target_machine_builder(lljit_builder, jtmb)
lljit = LLVM::Orc::LLJIT.new(lljit_builder)
# ... now gives me this cryptic error:
On the other hand, enabling emulated TLS: void LLVMExtEnableEmulatedTLS(LLVMTargetMachineRef M) {
reinterpret_cast<TargetMachine *>(M)->Options.EmulatedTLS = true;
} class Crystal::Codegen::Target
def to_target_machine(...)
# ...
target = LLVM::Target.from_triple(self.to_s)
machine = target.create_target_machine(...).not_nil!
machine.enable_global_isel = false
LibLLVMExt.enable_emulated_tls(machine)
machine
end
end breaks
|
Crystal uses two strategies to run codegen specs. If the snippet requires the prelude, then
::run
injects aprint
call, builds the code to an actual temporary executable, then inspects its output viaProcess.run
. Otherwise, Crystal uses LLVM's JIT compiler to compile and call an extra wrapper function that, more or less, forwards the result of__crystal_main
with an emptyargc
andargv
:crystal/src/compiler/crystal/codegen/codegen.cr
Lines 45 to 53 in 0b251d4
Here we focus on this case where
::run
would return anLLVM::GenericValue
. We want to extract a typed value that our specs can actually use, but it turns out only primitive integers, floats, and pointers can be returned:crystal/src/llvm/lib_llvm/execution_engine.cr
Lines 22 to 24 in 0b251d4
This makes returning multiple values, such as in #14087 (comment), rather inconvenient; structs and tuples cannot be returned by value, and must go through the heap. (Heap contents are preserved across the JIT function call, stack contents are not, so
pointerof
on a local variable inside the snippet will fail.)Here is a way around that. First, the wrapper function will accept an extra output parameter, rather than returning a value:
We also reserve space for the return type
T
we are interested in. After that, we obtain__evaluate_wrapper
's address, cast it to an appropriateProc
now that we have access toT
, and bypassLLVM::GenericValue
entirely:With the appropriate forwarding for
type
, we should be able to write specs like this:Note that there is no
to_i
after the firstrun
. The secondrun
assumes{Int32, Int32}
is binary-compatible between the spec runner itself and the compiled snippet, but this should hold true for all primitive values, regardless of the current compiler version. (Actually, we are already assuming the same forString
every time a prelude-less codegen spec returns one.) Apart from grouping related specs in onerun
, we could also avoid the error-prone use of&+
in scenarios such as this:crystal/spec/compiler/codegen/block_spec.cr
Lines 1435 to 1446 in 0b251d4
The text was updated successfully, but these errors were encountered: