From e2345f006ffcd17e41aa73b27890044a0e1f2218 Mon Sep 17 00:00:00 2001 From: antlilja Date: Sat, 2 Mar 2024 15:19:09 +0100 Subject: [PATCH 1/3] LLVM: Add enableBrokenDebugInfoCheck and getBrokenDebugInfo These functions allows the caller to find out wether the context encounters broken debug info or not. --- src/codegen/llvm/bindings.zig | 6 ++++++ src/zig_llvm.cpp | 20 ++++++++++++++++++++ src/zig_llvm.h | 3 +++ 3 files changed, 29 insertions(+) diff --git a/src/codegen/llvm/bindings.zig b/src/codegen/llvm/bindings.zig index affadef882..ee87aef6ac 100644 --- a/src/codegen/llvm/bindings.zig +++ b/src/codegen/llvm/bindings.zig @@ -37,6 +37,12 @@ pub const Context = opaque { pub const setOptBisectLimit = ZigLLVMSetOptBisectLimit; extern fn ZigLLVMSetOptBisectLimit(C: *Context, limit: c_int) void; + + pub const enableBrokenDebugInfoCheck = ZigLLVMEnableBrokenDebugInfoCheck; + extern fn ZigLLVMEnableBrokenDebugInfoCheck(C: *Context) void; + + pub const getBrokenDebugInfo = ZigLLVMGetBrokenDebugInfo; + extern fn ZigLLVMGetBrokenDebugInfo(C: *Context) bool; }; pub const Module = opaque { diff --git a/src/zig_llvm.cpp b/src/zig_llvm.cpp index e5432737f9..92364cc143 100644 --- a/src/zig_llvm.cpp +++ b/src/zig_llvm.cpp @@ -380,6 +380,26 @@ void ZigLLVMSetOptBisectLimit(LLVMContextRef context_ref, int limit) { unwrap(context_ref)->setOptPassGate(opt_bisect); } +struct ZigDiagnosticHandler : public DiagnosticHandler { + bool BrokenDebugInfo; + ZigDiagnosticHandler() : BrokenDebugInfo(false) {} + bool handleDiagnostics(const DiagnosticInfo &DI) override { + if (auto *Remark = dyn_cast(&DI)) { + BrokenDebugInfo = true; + } + return false; + } +}; + +void ZigLLVMEnableBrokenDebugInfoCheck(LLVMContextRef context_ref) { + unwrap(context_ref)->setDiagnosticHandler(std::make_unique()); +} + +bool ZigLLVMGetBrokenDebugInfo(LLVMContextRef context_ref) { + return ((const ZigDiagnosticHandler*) + unwrap(context_ref)->getDiagHandlerPtr())->BrokenDebugInfo; +} + void ZigLLVMParseCommandLineOptions(size_t argc, const char *const *argv) { cl::ParseCommandLineOptions(argc, argv); } diff --git a/src/zig_llvm.h b/src/zig_llvm.h index 56298e88bb..e133cb01b7 100644 --- a/src/zig_llvm.h +++ b/src/zig_llvm.h @@ -44,6 +44,9 @@ ZIG_EXTERN_C LLVMTargetMachineRef ZigLLVMCreateTargetMachine(LLVMTargetRef T, co ZIG_EXTERN_C void ZigLLVMSetOptBisectLimit(LLVMContextRef context_ref, int limit); +ZIG_EXTERN_C void ZigLLVMEnableBrokenDebugInfoCheck(LLVMContextRef context_ref); +ZIG_EXTERN_C bool ZigLLVMGetBrokenDebugInfo(LLVMContextRef context_ref); + enum ZigLLVMTailCallKind { ZigLLVMTailCallKindNone, ZigLLVMTailCallKindTail, From d345068ec2cf7275c931c4d79d46384c38132ffc Mon Sep 17 00:00:00 2001 From: antlilja Date: Sat, 2 Mar 2024 15:45:58 +0100 Subject: [PATCH 2/3] LLVM: Fail to emit if LLVM encounters broken debug info --- src/codegen/llvm.zig | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 82b204cacb..885b278607 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -1245,9 +1245,11 @@ pub const Object = struct { ); defer bitcode_memory_buffer.dispose(); + context.enableBrokenDebugInfoCheck(); + var module: *llvm.Module = undefined; - if (context.parseBitcodeInContext2(bitcode_memory_buffer, &module).toBool()) { - std.debug.print("Failed to parse bitcode\n", .{}); + if (context.parseBitcodeInContext2(bitcode_memory_buffer, &module).toBool() or context.getBrokenDebugInfo()) { + log.err("Failed to parse bitcode", .{}); return error.FailedToEmit; } break :emit .{ context, module }; From 282b398f6da967f413e223b452457d37e93a70b3 Mon Sep 17 00:00:00 2001 From: antlilja Date: Sun, 3 Mar 2024 02:28:24 +0100 Subject: [PATCH 3/3] Add comment explaining LLVM bug and linking tracking issue --- src/zig_llvm.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/zig_llvm.cpp b/src/zig_llvm.cpp index 92364cc143..ae1f02422b 100644 --- a/src/zig_llvm.cpp +++ b/src/zig_llvm.cpp @@ -384,6 +384,11 @@ struct ZigDiagnosticHandler : public DiagnosticHandler { bool BrokenDebugInfo; ZigDiagnosticHandler() : BrokenDebugInfo(false) {} bool handleDiagnostics(const DiagnosticInfo &DI) override { + // This dyn_cast should be casting to DiagnosticInfoIgnoringInvalidDebugMetadata + // but DiagnosticInfoIgnoringInvalidDebugMetadata is treated as DiagnosticInfoDebugMetadataVersion + // because of a bug in LLVM (see https://github.com/ziglang/zig/issues/19161). + // After this is fixed add an additional check for DiagnosticInfoIgnoringInvalidDebugMetadata + // but don't remove the current one as both indicate that debug info is broken. if (auto *Remark = dyn_cast(&DI)) { BrokenDebugInfo = true; }