Open cpunion opened 2 months ago
Consider the following Go code:
var envs = []int{} func Test() int { defer print(1) a := 1 for _, env := range envs { if env != 1 { a = a + 1 } } return a }
This generates LLVM IR: (WRONG SAMPLE)
define i64 @main.Test() { _llgo_0: %0 = load i32, ptr @__llgo_defer, align 4 %1 = call ptr @pthread_getspecific(i32 %0) %2 = alloca i8, i64 196, align 1 %3 = alloca i8, i64 40, align 1 %4 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %3, i32 0, i32 0 store ptr %2, ptr %4, align 8 %5 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %3, i32 0, i32 1 store i64 0, ptr %5, align 4 %6 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %3, i32 0, i32 2 store ptr %1, ptr %6, align 8 %7 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %3, i32 0, i32 3 store ptr blockaddress(@main.Test, %_llgo_6), ptr %7, align 8 %8 = call i32 @pthread_setspecific(i32 %0, ptr %3) %9 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %3, i32 0, i32 1 %10 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %3, i32 0, i32 3 %11 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %3, i32 0, i32 4 %12 = call i32 @sigsetjmp(ptr %2, i32 0) %13 = icmp eq i32 %12, 0 br i1 %13, label %_llgo_8, label %_llgo_9 _llgo_1: ; preds = %_llgo_7 ret i64 0 _llgo_2: ; preds = %_llgo_5, %_llgo_3, %_llgo_8 %14 = phi i64 [ 1, %_llgo_8 ], [ %14, %_llgo_3 ], [ %26, %_llgo_5 ] %15 = phi i64 [ -1, %_llgo_8 ], [ %16, %_llgo_3 ], [ %16, %_llgo_5 ] %16 = add i64 %15, 1 %17 = icmp slt i64 %16, %33 br i1 %17, label %_llgo_3, label %_llgo_4 _llgo_3: ; preds = %_llgo_2 %18 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %32, 0 %19 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %32, 1 %20 = icmp slt i64 %16, 0 %21 = icmp sge i64 %16, %19 %22 = or i1 %21, %20 call void @"github.com/goplus/llgo/internal/runtime.AssertIndexRange"(i1 %22) %23 = getelementptr inbounds i64, ptr %18, i64 %16 %24 = load i64, ptr %23, align 4 %25 = icmp ne i64 %24, 1 br i1 %25, label %_llgo_5, label %_llgo_2 _llgo_4: ; preds = %_llgo_2 store ptr blockaddress(@main.Test, %_llgo_10), ptr %11, align 8 br label %_llgo_6 _llgo_5: ; preds = %_llgo_3 %26 = add i64 %14, 1 br label %_llgo_2 _llgo_6: ; preds = %_llgo_9, %_llgo_4 store ptr blockaddress(@main.Test, %_llgo_7), ptr %10, align 8 %27 = load i64, ptr %9, align 4 call void @"github.com/goplus/llgo/internal/runtime.PrintInt"(i64 1) %28 = load %"github.com/goplus/llgo/internal/runtime.Defer", ptr %3, align 8 %29 = extractvalue %"github.com/goplus/llgo/internal/runtime.Defer" %28, 2 %30 = call i32 @pthread_setspecific(i32 %0, ptr %29) %31 = load ptr, ptr %11, align 8 indirectbr ptr %31, [label %_llgo_7, label %_llgo_10] _llgo_7: ; preds = %_llgo_9, %_llgo_6 call void @"github.com/goplus/llgo/internal/runtime.Rethrow"(ptr %1) br label %_llgo_1 _llgo_8: ; preds = %_llgo_0 %32 = load %"github.com/goplus/llgo/internal/runtime.Slice", ptr @main.envs, align 8 %33 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %32, 1 br label %_llgo_2 _llgo_9: ; preds = %_llgo_0 store ptr blockaddress(@main.Test, %_llgo_7), ptr %11, align 8 %34 = load ptr, ptr %10, align 8 indirectbr ptr %34, [label %_llgo_7, label %_llgo_6] _llgo_10: ; preds = %_llgo_6 ret i64 %14 }
Compile it with llc:
llc
$ /opt/homebrew/bin/llc llgo_autogen.ll Instruction does not dominate all uses! %14 = phi i64 [ 1, %_llgo_8 ], [ %14, %_llgo_3 ], [ %26, %_llgo_5 ] ret i64 %14
But it can be compiled by clang:
clang
/opt/homebrew/bin/clang -c llgo_autogen.ll warning: overriding the module target triple with arm64-apple-macosx14.0.0 [-Woverride-module] 1 warning generated.
When generate code with debug info, the code almost same except debug info:
define i64 @main.Test() !dbg !22 { _llgo_0: %0 = load i32, ptr @__llgo_defer, align 4, !dbg !25 %1 = call ptr @pthread_getspecific(i32 %0), !dbg !25 %2 = alloca i8, i64 196, align 1, !dbg !25 %3 = alloca i8, i64 40, align 1, !dbg !25 %4 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %3, i32 0, i32 0, !dbg !25 store ptr %2, ptr %4, align 8, !dbg !25 %5 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %3, i32 0, i32 1, !dbg !25 store i64 0, ptr %5, align 4, !dbg !25 %6 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %3, i32 0, i32 2, !dbg !25 store ptr %1, ptr %6, align 8, !dbg !25 %7 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %3, i32 0, i32 3, !dbg !25 store ptr blockaddress(@main.Test, %_llgo_6), ptr %7, align 8, !dbg !25 %8 = call i32 @pthread_setspecific(i32 %0, ptr %3), !dbg !25 %9 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %3, i32 0, i32 1, !dbg !25 %10 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %3, i32 0, i32 3, !dbg !25 %11 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %3, i32 0, i32 4, !dbg !25 %12 = call i32 @sigsetjmp(ptr %2, i32 0), !dbg !25 %13 = icmp eq i32 %12, 0, !dbg !25 br i1 %13, label %_llgo_8, label %_llgo_9, !dbg !25 _llgo_1: ; preds = %_llgo_7 ret i64 0, !dbg !26 _llgo_2: ; preds = %_llgo_5, %_llgo_3, %_llgo_8 %14 = phi i64 [ 1, %_llgo_8 ], [ %14, %_llgo_3 ], [ %26, %_llgo_5 ], !dbg !25 %15 = phi i64 [ -1, %_llgo_8 ], [ %16, %_llgo_3 ], [ %16, %_llgo_5 ], !dbg !25 %16 = add i64 %15, 1, !dbg !26 %17 = icmp slt i64 %16, %33, !dbg !26 br i1 %17, label %_llgo_3, label %_llgo_4, !dbg !26 _llgo_3: ; preds = %_llgo_2 %18 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %32, 0, !dbg !27 %19 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %32, 1, !dbg !27 %20 = icmp slt i64 %16, 0, !dbg !27 %21 = icmp sge i64 %16, %19, !dbg !27 %22 = or i1 %21, %20, !dbg !27 call void @"github.com/goplus/llgo/internal/runtime.AssertIndexRange"(i1 %22), !dbg !27 %23 = getelementptr inbounds i64, ptr %18, i64 %16, !dbg !27 %24 = load i64, ptr %23, align 4, !dbg !26 call void @llvm.dbg.value(metadata i64 %24, metadata !28, metadata !DIExpression()), !dbg !29 call void @llvm.dbg.value(metadata i64 %24, metadata !28, metadata !DIExpression()), !dbg !30 %25 = icmp ne i64 %24, 1, !dbg !31 br i1 %25, label %_llgo_5, label %_llgo_2, !dbg !31 _llgo_4: ; preds = %_llgo_2 call void @llvm.dbg.value(metadata i64 %14, metadata !32, metadata !DIExpression()), !dbg !33 store ptr blockaddress(@main.Test, %_llgo_10), ptr %11, align 8, !dbg !34 br label %_llgo_6, !dbg !34 _llgo_5: ; preds = %_llgo_3 call void @llvm.dbg.value(metadata i64 %14, metadata !32, metadata !DIExpression()), !dbg !35 %26 = add i64 %14, 1, !dbg !34 call void @llvm.dbg.value(metadata i64 %26, metadata !32, metadata !DIExpression()), !dbg !36 br label %_llgo_2, !dbg !34 _llgo_6: ; preds = %_llgo_9, %_llgo_4 store ptr blockaddress(@main.Test, %_llgo_7), ptr %10, align 8, !dbg !34 %27 = load i64, ptr %9, align 4, !dbg !34 call void @"github.com/goplus/llgo/internal/runtime.PrintInt"(i64 1), !dbg !34 %28 = load %"github.com/goplus/llgo/internal/runtime.Defer", ptr %3, align 8, !dbg !34 %29 = extractvalue %"github.com/goplus/llgo/internal/runtime.Defer" %28, 2, !dbg !34 %30 = call i32 @pthread_setspecific(i32 %0, ptr %29), !dbg !34 %31 = load ptr, ptr %11, align 8, !dbg !34 indirectbr ptr %31, [label %_llgo_7, label %_llgo_10], !dbg !34 _llgo_7: ; preds = %_llgo_9, %_llgo_6 call void @"github.com/goplus/llgo/internal/runtime.Rethrow"(ptr %1), !dbg !25 br label %_llgo_1, !dbg !25 _llgo_8: ; preds = %_llgo_0 call void @llvm.dbg.value(metadata i64 1, metadata !32, metadata !DIExpression()), !dbg !37 %32 = load %"github.com/goplus/llgo/internal/runtime.Slice", ptr @main.envs, align 8, !dbg !27 call void @llvm.dbg.value(metadata %"github.com/goplus/llgo/internal/runtime.Slice" %32, metadata !38, metadata !DIExpression()), !dbg !27 %33 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %32, 1, !dbg !26 br label %_llgo_2, !dbg !26 _llgo_9: ; preds = %_llgo_0 store ptr blockaddress(@main.Test, %_llgo_7), ptr %11, align 8, !dbg !34 %34 = load ptr, ptr %10, align 8, !dbg !34 indirectbr ptr %34, [label %_llgo_7, label %_llgo_6], !dbg !34 _llgo_10: ; preds = %_llgo_6 ret i64 %14, !dbg !34 }
When remove the debug tokens and lines, it is no difference between them.
$ /opt/homebrew/bin/llc llgo_autogen.ll Instruction does not dominate all uses! %14 = phi i64 [ 1, %_llgo_8 ], [ %14, %_llgo_3 ], [ %26, %_llgo_5 ], !dbg !25 ret i64 %14, !dbg !34 LLVM ERROR: Broken module found, compilation aborted! PLEASE submit a bug report to https://github.com/Homebrew/homebrew-core/issues and include the crash backtrace. Stack dump: 0. Program arguments: /opt/homebrew/bin/llc llgo_autogen.ll #0 0x0000000111fe1d60 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/homebrew/Cellar/llvm/18.1.8/lib/libLLVM.dylib+0x4695d60) #1 0x0000000111fe2134 SignalHandler(int) (/opt/homebrew/Cellar/llvm/18.1.8/lib/libLLVM.dylib+0x4696134) #2 0x00000001805f7584 (/usr/lib/system/libsystem_platform.dylib+0x180477584) #3 0x00000001805c6c20 (/usr/lib/system/libsystem_pthread.dylib+0x180446c20) #4 0x00000001804d3a20 (/usr/lib/system/libsystem_c.dylib+0x180353a20) #5 0x000000010d9e7da0 llvm::report_fatal_error(llvm::Twine const&, bool) (/opt/homebrew/Cellar/llvm/18.1.8/lib/libLLVM.dylib+0x9bda0) #6 0x0000000111fd4870 llvm::report_fatal_error(llvm::StringRef, bool) (/opt/homebrew/Cellar/llvm/18.1.8/lib/libLLVM.dylib+0x4688870) #7 0x000000010db08d10 llvm::UpgradeDebugInfo(llvm::Module&) (/opt/homebrew/Cellar/llvm/18.1.8/lib/libLLVM.dylib+0x1bcd10) #8 0x00000001119addd4 llvm::LLParser::validateEndOfModule(bool) (/opt/homebrew/Cellar/llvm/18.1.8/lib/libLLVM.dylib+0x4061dd4) #9 0x00000001119ac984 llvm::LLParser::Run(bool, llvm::function_ref<std::__1::optional<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>> (llvm::StringRef, llvm::StringRef)>) (/opt/homebrew/Cellar/llvm/18.1.8/lib/libLLVM.dylib+0x4060984) #10 0x00000001119e7e90 parseAssemblyInto(llvm::MemoryBufferRef, llvm::Module*, llvm::ModuleSummaryIndex*, llvm::SMDiagnostic&, llvm::SlotMapping*, bool, llvm::function_ref<std::__1::optional<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>> (llvm::StringRef, llvm::StringRef)>) (/opt/homebrew/Cellar/llvm/18.1.8/lib/libLLVM.dylib+0x409be90) #11 0x00000001119e8138 llvm::parseAssembly(llvm::MemoryBufferRef, llvm::SMDiagnostic&, llvm::LLVMContext&, llvm::SlotMapping*, llvm::function_ref<std::__1::optional<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>> (llvm::StringRef, llvm::StringRef)>) (/opt/homebrew/Cellar/llvm/18.1.8/lib/libLLVM.dylib+0x409c138) #12 0x000000010dd877e8 llvm::parseIR(llvm::MemoryBufferRef, llvm::SMDiagnostic&, llvm::LLVMContext&, llvm::ParserCallbacks) (/opt/homebrew/Cellar/llvm/18.1.8/lib/libLLVM.dylib+0x43b7e8) #13 0x000000010dd881e0 llvm::parseIRFile(llvm::StringRef, llvm::SMDiagnostic&, llvm::LLVMContext&, llvm::ParserCallbacks) (/opt/homebrew/Cellar/llvm/18.1.8/lib/libLLVM.dylib+0x43c1e0) #14 0x00000001048b9428 compileModule(char**, llvm::LLVMContext&) (/opt/homebrew/Cellar/llvm/18.1.8/bin/llc+0x100005428) #15 0x00000001048b84a8 main (/opt/homebrew/Cellar/llvm/18.1.8/bin/llc+0x1000044a8) #16 0x000000018023e0e0 [1] 77142 abort /opt/homebrew/bin/llc llgo_autogen.ll
Compile it with clang:
$ /opt/homebrew/bin/clang -c llgo_autogen.ll Instruction does not dominate all uses! %14 = phi i64 [ 1, %_llgo_8 ], [ %14, %_llgo_3 ], [ %26, %_llgo_5 ], !dbg !25 ret i64 %14, !dbg !34 fatal error: error in backend: Broken module found, compilation aborted! PLEASE submit a bug report to https://github.com/Homebrew/homebrew-core/issues and include the crash backtrace, preprocessed source, and associated run script. Stack dump: 0. Program arguments: /opt/homebrew/bin/clang -c llgo_autogen.ll #0 0x000000011aeb9d60 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/homebrew/Cellar/llvm/18.1.8/lib/libLLVM.dylib+0x4695d60) #1 0x0000000116979560 llvm::sys::CleanupOnSignal(unsigned long) (/opt/homebrew/Cellar/llvm/18.1.8/lib/libLLVM.dylib+0x155560) #2 0x000000011aeab718 (anonymous namespace)::CrashRecoveryContextImpl::HandleCrash(int, unsigned long) (/opt/homebrew/Cellar/llvm/18.1.8/lib/libLLVM.dylib+0x4687718) #3 0x000000011aeab6c8 llvm::CrashRecoveryContext::HandleExit(int) (/opt/homebrew/Cellar/llvm/18.1.8/lib/libLLVM.dylib+0x46876c8) #4 0x000000011aeb95b4 llvm::sys::Process::Exit(int, bool) (/opt/homebrew/Cellar/llvm/18.1.8/lib/libLLVM.dylib+0x46955b4) #5 0x0000000104323b8c LLVMErrorHandler(void*, char const*, bool) (/opt/homebrew/Cellar/llvm/18.1.8/bin/clang-18+0x100007b8c) #6 0x00000001168bfd74 llvm::report_fatal_error(llvm::Twine const&, bool) (/opt/homebrew/Cellar/llvm/18.1.8/lib/libLLVM.dylib+0x9bd74) #7 0x000000011aeac870 llvm::report_fatal_error(llvm::StringRef, bool) (/opt/homebrew/Cellar/llvm/18.1.8/lib/libLLVM.dylib+0x4688870) #8 0x00000001169e0d10 llvm::UpgradeDebugInfo(llvm::Module&) (/opt/homebrew/Cellar/llvm/18.1.8/lib/libLLVM.dylib+0x1bcd10) #9 0x000000011a885dd4 llvm::LLParser::validateEndOfModule(bool) (/opt/homebrew/Cellar/llvm/18.1.8/lib/libLLVM.dylib+0x4061dd4) #10 0x000000011a884984 llvm::LLParser::Run(bool, llvm::function_ref<std::__1::optional<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>> (llvm::StringRef, llvm::StringRef)>) (/opt/homebrew/Cellar/llvm/18.1.8/lib/libLLVM.dylib+0x4060984) #11 0x000000011a8bfe90 parseAssemblyInto(llvm::MemoryBufferRef, llvm::Module*, llvm::ModuleSummaryIndex*, llvm::SMDiagnostic&, llvm::SlotMapping*, bool, llvm::function_ref<std::__1::optional<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>> (llvm::StringRef, llvm::StringRef)>) (/opt/homebrew/Cellar/llvm/18.1.8/lib/libLLVM.dylib+0x409be90) #12 0x000000011a8c0138 llvm::parseAssembly(llvm::MemoryBufferRef, llvm::SMDiagnostic&, llvm::LLVMContext&, llvm::SlotMapping*, llvm::function_ref<std::__1::optional<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>> (llvm::StringRef, llvm::StringRef)>) (/opt/homebrew/Cellar/llvm/18.1.8/lib/libLLVM.dylib+0x409c138) #13 0x0000000116c5f7e8 llvm::parseIR(llvm::MemoryBufferRef, llvm::SMDiagnostic&, llvm::LLVMContext&, llvm::ParserCallbacks) (/opt/homebrew/Cellar/llvm/18.1.8/lib/libLLVM.dylib+0x43b7e8) #14 0x000000010ab07730 clang::CodeGenAction::loadModule(llvm::MemoryBufferRef) (/opt/homebrew/Cellar/llvm/18.1.8/lib/libclang-cpp.dylib+0x193f730) #15 0x000000010ab08774 clang::CodeGenAction::ExecuteAction() (/opt/homebrew/Cellar/llvm/18.1.8/lib/libclang-cpp.dylib+0x1940774) #16 0x000000010b264dd4 clang::FrontendAction::Execute() (/opt/homebrew/Cellar/llvm/18.1.8/lib/libclang-cpp.dylib+0x209cdd4) #17 0x000000010b1e7ad4 clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/opt/homebrew/Cellar/llvm/18.1.8/lib/libclang-cpp.dylib+0x201fad4) #18 0x000000010b2b7c28 clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/opt/homebrew/Cellar/llvm/18.1.8/lib/libclang-cpp.dylib+0x20efc28) #19 0x0000000104322b28 cc1_main(llvm::ArrayRef<char const*>, char const*, void*) (/opt/homebrew/Cellar/llvm/18.1.8/bin/clang-18+0x100006b28) #20 0x0000000104321218 ExecuteCC1Tool(llvm::SmallVectorImpl<char const*>&, llvm::ToolContext const&) (/opt/homebrew/Cellar/llvm/18.1.8/bin/clang-18+0x100005218) #21 0x000000010ae65d28 void llvm::function_ref<void ()>::callback_fn<clang::driver::CC1Command::Execute(llvm::ArrayRef<std::__1::optional<llvm::StringRef>>, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>*, bool*) const::$_0>(long) (/opt/homebrew/Cellar/llvm/18.1.8/lib/libclang-cpp.dylib+0x1c9dd28) #22 0x00000001168b0b48 llvm::CrashRecoveryContext::RunSafely(llvm::function_ref<void ()>) (/opt/homebrew/Cellar/llvm/18.1.8/lib/libLLVM.dylib+0x8cb48) #23 0x000000010ae65524 clang::driver::CC1Command::Execute(llvm::ArrayRef<std::__1::optional<llvm::StringRef>>, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>*, bool*) const (/opt/homebrew/Cellar/llvm/18.1.8/lib/libclang-cpp.dylib+0x1c9d524) #24 0x000000010ae26190 clang::driver::Compilation::ExecuteCommand(clang::driver::Command const&, clang::driver::Command const*&, bool) const (/opt/homebrew/Cellar/llvm/18.1.8/lib/libclang-cpp.dylib+0x1c5e190) #25 0x000000010ae46e00 clang::driver::Driver::ExecuteCompilation(clang::driver::Compilation&, llvm::SmallVectorImpl<std::__1::pair<int, clang::driver::Command const*>>&) (/opt/homebrew/Cellar/llvm/18.1.8/lib/libclang-cpp.dylib+0x1c7ee00) #26 0x000000010431fd44 clang_main(int, char**, llvm::ToolContext const&) (/opt/homebrew/Cellar/llvm/18.1.8/bin/clang-18+0x100003d44) #27 0x000000010432ce38 main (/opt/homebrew/Cellar/llvm/18.1.8/bin/clang-18+0x100010e38) #28 0x000000018023e0e0 clang: error: clang frontend command failed with exit code 70 (use -v to see invocation) Homebrew clang version 18.1.8 Target: arm64-apple-darwin23.4.0 Thread model: posix InstalledDir: /opt/homebrew/bin clang: note: diagnostic msg: Error generating preprocessed source(s) - no preprocessable inputs.
When remove the defer statement, it compile passed. The code generated:
defer
define i64 @main.Test() !dbg !22 { _llgo_0: call void @llvm.dbg.value(metadata i64 1, metadata !25, metadata !DIExpression()), !dbg !26 %0 = load %"github.com/goplus/llgo/internal/runtime.Slice", ptr @main.envs, align 8, !dbg !27 call void @llvm.dbg.value(metadata %"github.com/goplus/llgo/internal/runtime.Slice" %0, metadata !28, metadata !DIExpression()), !dbg !27 %1 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %0, 1, !dbg !29 br label %_llgo_1, !dbg !29 _llgo_1: ; preds = %_llgo_4, %_llgo_2, %_llgo_0 %2 = phi i64 [ 1, %_llgo_0 ], [ %2, %_llgo_2 ], [ %14, %_llgo_4 ], !dbg !30 %3 = phi i64 [ -1, %_llgo_0 ], [ %4, %_llgo_2 ], [ %4, %_llgo_4 ], !dbg !30 %4 = add i64 %3, 1, !dbg !29 %5 = icmp slt i64 %4, %1, !dbg !29 br i1 %5, label %_llgo_2, label %_llgo_3, !dbg !29 _llgo_2: ; preds = %_llgo_1 %6 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %0, 0, !dbg !27 %7 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %0, 1, !dbg !27 %8 = icmp slt i64 %4, 0, !dbg !27 %9 = icmp sge i64 %4, %7, !dbg !27 %10 = or i1 %9, %8, !dbg !27 call void @"github.com/goplus/llgo/internal/runtime.AssertIndexRange"(i1 %10), !dbg !27 %11 = getelementptr inbounds i64, ptr %6, i64 %4, !dbg !27 %12 = load i64, ptr %11, align 4, !dbg !29 call void @llvm.dbg.value(metadata i64 %12, metadata !31, metadata !DIExpression()), !dbg !32 call void @llvm.dbg.value(metadata i64 %12, metadata !31, metadata !DIExpression()), !dbg !33 %13 = icmp ne i64 %12, 1, !dbg !34 br i1 %13, label %_llgo_4, label %_llgo_1, !dbg !34 _llgo_3: ; preds = %_llgo_1 call void @llvm.dbg.value(metadata i64 %2, metadata !25, metadata !DIExpression()), !dbg !35 ret i64 %2, !dbg !36 _llgo_4: ; preds = %_llgo_2 call void @llvm.dbg.value(metadata i64 %2, metadata !25, metadata !DIExpression()), !dbg !37 %14 = add i64 %2, 1, !dbg !36 call void @llvm.dbg.value(metadata i64 %14, metadata !25, metadata !DIExpression()), !dbg !38 br label %_llgo_1, !dbg !36 }
The flow graph of code block WRONG SAMPLE
WRONG SAMPLE
There was a wrong path from _llgo_0 to _llgo_10 that didn't through _llgo_2, and the return value is allocated in _llgo_2. Maybe it's jumping correctly by the blockaddress, but it can't pass the compiling.
_llgo_0
_llgo_10
_llgo_2
It led to this issue: https://github.com/goplus/llgo/actions/runs/10971740620/job/30467224448?pr=794
Below is the right path, the _llgo_1 (same as _llgo_2 in the defer version) is always executed.
_llgo_1
Description
Current behavior
Consider the following Go code:
This generates LLVM IR: (WRONG SAMPLE)
Compile it with
llc
:But it can be compiled by
clang
:When generate code with debug info, the code almost same except debug info:
When remove the debug tokens and lines, it is no difference between them.
Compile it with
llc
:Compile it with
clang
:When remove the
defer
statement, it compile passed. The code generated:The flow graph of code block
WRONG SAMPLE
There was a wrong path from
_llgo_0
to_llgo_10
that didn't through_llgo_2
, and the return value is allocated in_llgo_2
. Maybe it's jumping correctly by the blockaddress, but it can't pass the compiling.It led to this issue: https://github.com/goplus/llgo/actions/runs/10971740620/job/30467224448?pr=794
Below is the right path, the
_llgo_1
(same as_llgo_2
in the defer version) is always executed.