From da520f5c6baecbe7623393dc543255e58541bcb9 Mon Sep 17 00:00:00 2001 From: Quinton Miller Date: Thu, 19 Sep 2024 21:19:08 +0800 Subject: [PATCH] fixup --- spec/compiler/codegen/debug_spec.cr | 2 -- src/compiler/crystal/codegen/debug.cr | 16 ++++++++++++++++ src/intrinsics.cr | 9 +++++++-- 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/spec/compiler/codegen/debug_spec.cr b/spec/compiler/codegen/debug_spec.cr index 4a57056fc7a3..0032fcb64b4c 100644 --- a/spec/compiler/codegen/debug_spec.cr +++ b/spec/compiler/codegen/debug_spec.cr @@ -160,8 +160,6 @@ describe "Code gen: debug" do it "has debug info in closure inside if (#5593)" do codegen(%( - require "prelude" - def foo if true && true yield 1 diff --git a/src/compiler/crystal/codegen/debug.cr b/src/compiler/crystal/codegen/debug.cr index 72555d074bb0..9a03420ba203 100644 --- a/src/compiler/crystal/codegen/debug.cr +++ b/src/compiler/crystal/codegen/debug.cr @@ -367,6 +367,16 @@ module Crystal old_debug_location = @current_debug_location set_current_debug_location location if builder.current_debug_location != llvm_nil && (ptr = alloca) + # FIXME: When debug records are used instead of debug intrinsics, it + # seems inserting them into an empty BasicBlock will instead place them + # in a totally different (next?) function where the variable doesn't + # exist, leading to a "function-local metadata used in wrong function" + # validation error. This might happen when e.g. all variables inside a + # block are closured. Ideally every debug record should immediately + # follow the variable it declares. + {% unless LibLLVM::IS_LT_190 %} + call(do_nothing_fun) if block.instructions.empty? + {% end %} di_builder.insert_declare_at_end(ptr, var, expr, builder.current_debug_location_metadata, block) set_current_debug_location old_debug_location true @@ -376,6 +386,12 @@ module Crystal end end + private def do_nothing_fun + fetch_typed_fun(@llvm_mod, "llvm.donothing") do + LLVM::Type.function([] of LLVM::Type, @llvm_context.void) + end + end + # Emit debug info for toplevel variables. Used for the main module and all # required files. def emit_vars_debug_info(vars) diff --git a/src/intrinsics.cr b/src/intrinsics.cr index 7cdc462ce543..dc83ab91c884 100644 --- a/src/intrinsics.cr +++ b/src/intrinsics.cr @@ -163,8 +163,13 @@ lib LibIntrinsics {% if flag?(:interpreted) %} @[Primitive(:interpreter_intrinsics_fshr128)] {% end %} fun fshr128 = "llvm.fshr.i128"(a : UInt128, b : UInt128, count : UInt128) : UInt128 - fun va_start = "llvm.va_start"(ap : Void*) - fun va_end = "llvm.va_end"(ap : Void*) + {% if compare_versions(Crystal::LLVM_VERSION, "19.1.0") < 0 %} + fun va_start = "llvm.va_start"(ap : Void*) + fun va_end = "llvm.va_end"(ap : Void*) + {% else %} + fun va_start = "llvm.va_start.p0"(ap : Void*) + fun va_end = "llvm.va_end.p0"(ap : Void*) + {% end %} {% if flag?(:i386) || flag?(:x86_64) %} {% if flag?(:interpreted) %} @[Primitive(:interpreter_intrinsics_pause)] {% end %}