Skip to content

[EDDI] Transforming a noexcept function could lead to malformed code #2

@EmilioCorigliano

Description

@EmilioCorigliano

Trying to perform the EDDI transformation on the following TestNoExcept function leads to a malformed code.

class myclass
{
public:
    myclass() {}
};

void TestNoExcept() noexcept { volatile myclass m_data; }

The LLVM-IR input to the EDDI module is the following:

; Function Attrs: mustprogress noinline nounwind optnone
define dso_local void @_Z12TestNoExceptv() #0 personality ptr @__gxx_personality_v0 !dbg !16 {
  %1 = alloca %class.myclass, align 1
  call void @llvm.dbg.declare(metadata ptr %1, metadata !20, metadata !DIExpression()), !dbg !22
  %2 = invoke noundef ptr @_ZN7myclassC2Ev(ptr noundef nonnull align 1 dereferenceable(1) %1)
          to label %3 unwind label %4, !dbg !22

3:                                                ; preds = %0
  ret void, !dbg !23

4:                                                ; preds = %0
  %5 = landingpad { ptr, i32 }
          catch ptr null, !dbg !22
  %6 = extractvalue { ptr, i32 } %5, 0, !dbg !22
  call void @__clang_call_terminate(ptr %6) #4, !dbg !22
  unreachable, !dbg !22
}

The EDDI LLVM-IR output is the following:

; Function Attrs: mustprogress noinline nounwind optnone
define dso_local void @_Z12TestNoExceptv_dup() #0 personality ptr @__gxx_personality_v0 !dbg !54 {
  %1 = alloca %class.myclass, align 1
  br label %VerificationBB, !dbg !55

VerificationBB:                                   ; preds = %0
  br label %2, !dbg !55

2:                                                ; preds = %VerificationBB
  call void @llvm.dbg.declare(metadata ptr %1, metadata !56, metadata !DIExpression()), !dbg !55
  %3 = alloca %class.myclass, align 1
  br label %VerificationBB1, !dbg !55

VerificationBB1:                                  ; preds = %2
  br label %4, !dbg !55

4:                                                ; preds = %VerificationBB1
  %5 = invoke ptr @_ZN7myclassC2Ev_dup(ptr %1, ptr %3)
          to label %6 unwind label %VerificationBB2, !dbg !55

6:                                                ; preds = %4
  ret void, !dbg !57

7:                                                ; No predecessors!
  %8 = landingpad { ptr, i32 }
          catch ptr null, !dbg !55
  %9 = extractvalue { ptr, i32 } %8, 0, !dbg !55
  %10 = extractvalue { ptr, i32 } %8, 0, !dbg !55
  br label %VerificationBB2, !dbg !55

VerificationBB2:                                  ; preds = %4, %7
  br label %11, !dbg !55

11:                                               ; preds = %VerificationBB2
  call void @__clang_call_terminate_dup(ptr %9, ptr %10), !dbg !55
  unreachable, !dbg !55
}

The compilation error is the following:

The unwind destination does not have an exception handling instruction!
  %5 = invoke ptr @_ZN7myclassC2Ev_dup(ptr %1, ptr %3)
          to label %6 unwind label %VerificationBB2, !dbg !20
Instruction does not dominate all uses!
  %9 = extractvalue { ptr, i32 } %8, 0, !dbg !20
  call void @__clang_call_terminate_dup(ptr %9, ptr %10), !dbg !20
Instruction does not dominate all uses!
  %10 = extractvalue { ptr, i32 } %8, 0, !dbg !20
  call void @__clang_call_terminate_dup(ptr %9, ptr %10), !dbg !20
The unwind destination does not have an exception handling instruction!
  %5 = invoke ptr @_ZN7myclassC2Ev_dup(ptr %1, ptr %3)
          to label %6 unwind label %VerificationBB2, !dbg !55
Instruction does not dominate all uses!
  %9 = extractvalue { ptr, i32 } %8, 0, !dbg !55
  call void @__clang_call_terminate_dup(ptr %9, ptr %10), !dbg !55
Instruction does not dominate all uses!
  %10 = extractvalue { ptr, i32 } %8, 0, !dbg !55
  call void @__clang_call_terminate_dup(ptr %9, ptr %10), !dbg !55
LLVM ERROR: Broken module found, compilation aborted!
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0.	Program arguments: /home/streben/Documenti/llvm-project/build/bin/opt -load-pass-plugin=/home/streben/Documenti/POLIMI/TESI/ASPIS/build/passes/libSEDDI.so --passes=eddi-verify ret_to_ref.bc -o out.bc
 #0 0x0000000004479646 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) /home/streben/Documenti/llvm-project/llvm/lib/Support/Unix/Signals.inc:723:22
 #1 0x0000000004479a84 PrintStackTraceSignalHandler(void*) /home/streben/Documenti/llvm-project/llvm/lib/Support/Unix/Signals.inc:798:1
 #2 0x0000000004477286 llvm::sys::RunSignalHandlers() /home/streben/Documenti/llvm-project/llvm/lib/Support/Signals.cpp:105:20
 #3 0x0000000004479018 SignalHandler(int) /home/streben/Documenti/llvm-project/llvm/lib/Support/Unix/Signals.inc:413:1
 #4 0x00007f94de73dd00 __restore_rt (/lib64/libc.so.6+0x40d00)
 #5 0x00007f94de796664 __pthread_kill_implementation (/lib64/libc.so.6+0x99664)
 #6 0x00007f94de73dc4e gsignal (/lib64/libc.so.6+0x40c4e)
 #7 0x00007f94de725902 abort (/lib64/libc.so.6+0x28902)
 #8 0x00000000043ab122 llvm::report_fatal_error(llvm::Twine const&, bool) /home/streben/Documenti/llvm-project/llvm/lib/Support/ErrorHandling.cpp:125:9
 #9 0x00000000043aaf3b llvm::report_fatal_error(llvm::StringRef, bool) /home/streben/Documenti/llvm-project/llvm/lib/Support/ErrorHandling.cpp:86:68
#10 0x0000000003c7ec07 llvm::VerifierPass::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) /home/streben/Documenti/llvm-project/llvm/lib/IR/Verifier.cpp:7162:33
#11 0x000000000091c73a llvm::detail::PassModel<llvm::Module, llvm::VerifierPass, llvm::PreservedAnalyses, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) /home/streben/Documenti/llvm-project/llvm/include/llvm/IR/PassManagerInternal.h:90:3
#12 0x0000000003c08d13 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) /home/streben/Documenti/llvm-project/llvm/include/llvm/IR/PassManager.h:547:20
#13 0x00000000008f8b01 llvm::runPassPipeline(llvm::StringRef, llvm::Module&, llvm::TargetMachine*, llvm::TargetLibraryInfoImpl*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::StringRef, llvm::ArrayRef<llvm::PassPlugin>, llvm::opt_tool::OutputKind, llvm::opt_tool::VerifierKind, bool, bool, bool, bool, bool, bool, bool) /home/streben/Documenti/llvm-project/llvm/tools/opt/NewPMDriver.cpp:527:10
#14 0x0000000000922667 main /home/streben/Documenti/llvm-project/llvm/tools/opt/opt.cpp:739:27
#15 0x00007f94de727088 __libc_start_call_main (/lib64/libc.so.6+0x2a088)
#16 0x00007f94de72714b __libc_start_main@GLIBC_2.2.5 (/lib64/libc.so.6+0x2a14b)
#17 0x00000000008f5fe5 _start (/home/streben/Documenti/llvm-project/build/bin/opt+0x8f5fe5)

The original invoke with output going in %2 is the invoke that causes the verify step to fail when transformed in the invoke with output going in %5 of the EDDI output code.

The unwind label points to %VerificationBB2 instead of %7 and, for this, the basic block 7: is noted to have no predecessors. Also, the unwind destination label points to a basic block which doesn't handle the exception.

Note that this happens only if the 'noexcept' specifier is present and if 'myArray' has a non-default constructor.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions