Open etcimon opened 9 months ago
testcase: https://d.godbolt.org/z/fbMborTez
I've found the issue. Reproducer with LLC: https://llvm.godbolt.org/z/3bj1rT794
target datalayout = "e-m:e-p:64:64-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20"
target triple = "wasm64-unknown-unknown"
define void @foo() personality ptr @_d_eh_personality {
unreachable
}
declare i32 @_d_eh_personality(i32, i32, i64, ptr, ptr)
declare i32 @__gxx_wasm_personality_v0(...)
_d_eh_personality
is not recognized by LLVM as a "scoped EH personality function"
https://github.com/llvm/llvm-project/blob/9423e459875b0dcdf24975976838d651a92f1bdb/llvm/lib/CodeGen/MachineFunction.cpp#L240-L243
https://github.com/llvm/llvm-project/blob/9423e459875b0dcdf24975976838d651a92f1bdb/llvm/lib/IR/EHPersonalities.cpp#L23-L46
If we'd use __gxx_wasm_personality_v0
as personality function, then there'd be no crash. But I can't find any implementation for that function, or other documentation.
Here is the stack trace for a simple try/catch
Assertion failed: R == 0 && "Already initialized this value register!", file F:\Development\llvm-project\llvm\include\llvm/CodeGen/FunctionLoweringInfo.h, line 222
Exception Code: 0x80000003
#0 0x00007ff7b7e688dc HandleAbort F:\Development\llvm-project\llvm\lib\Support\Windows\Signals.inc:419:0
#1 0x00007ff80f958e05 (C:\Windows\SYSTEM32\ucrtbased.dll+0xa8e05)
#2 0x00007ff80f95ab29 (C:\Windows\SYSTEM32\ucrtbased.dll+0xaab29)
#3 0x00007ff80f961025 (C:\Windows\SYSTEM32\ucrtbased.dll+0xb1025)
#4 0x00007ff80f9608b7 (C:\Windows\SYSTEM32\ucrtbased.dll+0xb08b7)
#5 0x00007ff80f95e881 (C:\Windows\SYSTEM32\ucrtbased.dll+0xae881)
#6 0x00007ff80f96158f (C:\Windows\SYSTEM32\ucrtbased.dll+0xb158f)
#7 0x00007ff7b53dc03d llvm::FunctionLoweringInfo::InitializeRegForValue(class llvm::Value const *) F:\Development\llvm-project\llvm\include\llvm\CodeGen\FunctionLoweringInfo.h:222:0
#8 0x00007ff7b53499a2 llvm::SelectionDAGBuilder::getValueImpl(class llvm::Value const *) F:\Development\llvm-project\llvm\lib\CodeGen\SelectionDAG\SelectionDAGBuilder.cpp:1784:0
#9 0x00007ff7b53479d9 llvm::SelectionDAGBuilder::getNonRegisterValue(class llvm::Value const *) F:\Development\llvm-project\llvm\lib\CodeGen\SelectionDAG\SelectionDAGBuilder.cpp:1637:0
#10 0x00007ff7b5343ea2 llvm::SelectionDAGBuilder::CopyValueToVirtualRegister(class llvm::Value const *, unsigned int, enum llvm::ISD::NodeType) F:\Development\llvm-project\llvm\lib\CodeGen\SelectionDAG\SelectionDAGBuilder.cpp:10485:0
#11 0x00007ff7b534b07f llvm::SelectionDAGBuilder::CopyToExportRegsIfNeeded(class llvm::Value const *) F:\Development\llvm-project\llvm\lib\CodeGen\SelectionDAG\SelectionDAGBuilder.cpp:2183:0
#12 0x00007ff7b534477c llvm::SelectionDAGBuilder::visit(class llvm::Instruction const &) F:\Development\llvm-project\llvm\lib\CodeGen\SelectionDAG\SelectionDAGBuilder.cpp:1198:0
#13 0x00007ff7b53f9650 llvm::SelectionDAGISel::SelectBasicBlock(class llvm::ilist_iterator<struct llvm::ilist_detail::node_options<class llvm::Instruction, 1, 0, void>, 0, 1>, class llvm::ilist_iterator<struct llvm::ilist_detail::node_options<class llvm::Instruction, 1, 0, void>, 0, 1>, bool &) F:\Development\llvm-project\llvm\lib\CodeGen\SelectionDAG\SelectionDAGISel.cpp:692:0
#14 0x00007ff7b53f9209 llvm::SelectionDAGISel::SelectAllBasicBlocks(class llvm::Function const &) F:\Development\llvm-project\llvm\lib\CodeGen\SelectionDAG\SelectionDAGISel.cpp:1705:0
#15 0x00007ff7b53eb348 llvm::SelectionDAGISel::runOnMachineFunction(class llvm::MachineFunction &) F:\Development\llvm-project\llvm\lib\CodeGen\SelectionDAG\SelectionDAGISel.cpp:483:0
#16 0x00007ff7b34a6c08 `anonymous namespace'::WebAssemblyDAGToDAGISel::runOnMachineFunction F:\Development\llvm-project\llvm\lib\Target\WebAssembly\WebAssemblyISelDAGToDAG.cpp:61:0
#17 0x00007ff7b5b4f2e4 llvm::MachineFunctionPass::runOnFunction(class llvm::Function &) F:\Development\llvm-project\llvm\lib\CodeGen\MachineFunctionPass.cpp:91:0
#18 0x00007ff7b793f68e llvm::FPPassManager::runOnFunction(class llvm::Function &) F:\Development\llvm-project\llvm\lib\IR\LegacyPassManager.cpp:1435:0
#19 0x00007ff7b793fa67 llvm::FPPassManager::runOnModule(class llvm::Module &) F:\Development\llvm-project\llvm\lib\IR\LegacyPassManager.cpp:1481:0
#20 0x00007ff7b7942885 `anonymous namespace'::MPPassManager::runOnModule F:\Development\llvm-project\llvm\lib\IR\LegacyPassManager.cpp:1550:0
#21 0x00007ff7b7943737 llvm::legacy::PassManagerImpl::run(class llvm::Module &) F:\Development\llvm-project\llvm\lib\IR\LegacyPassManager.cpp:535:0
#22 0x00007ff7b793880c llvm::legacy::PassManager::run(class llvm::Module &) F:\Development\llvm-project\llvm\lib\IR\LegacyPassManager.cpp:1678:0
#23 0x00007ff7b2966741 `anonymous namespace'::codegenModule F:\Development\ldc\driver\toobj.cpp:138:0
#24 0x00007ff7b29674e8 `anonymous namespace'::writeObjectFile F:\Development\ldc\driver\toobj.cpp:293:0
#25 0x00007ff7b296602b writeModule(class llvm::Module *, char const *) F:\Development\ldc\driver\toobj.cpp:488:0
#26 0x00007ff7b2852892 ldc::CodeGenerator::writeAndFreeLLModule(char const *) F:\Development\ldc\driver\codegenerator.cpp:294:0
#27 0x00007ff7b28520d4 ldc::CodeGenerator::~CodeGenerator(void) F:\Development\ldc\driver\codegenerator.cpp:223:0
#28 0x00007ff7b2744c9c codegenModules(struct Array<class Module *> &) F:\Development\ldc\driver\main.cpp:1331:0
#29 0x00007ff7b2472e54 mars_mainBody(struct Param &, struct Array<char const *> &, struct Array<char const *> &) F:\Development\ldc\dmd\main.d:753:0
#30 0x00007ff7b27444eb cppmain(void) F:\Development\ldc\driver\main.cpp:1236:0
#31 0x00007ff7b236874c D main F:\Development\ldc\driver\main.d:27:0
#32 0x00007ff7b265884c rt.dmain2._d_run_main2.runAll.__lambda2 D:\a\ldc\ldc\runtime\druntime\src\rt\dmain2.d:506:0
#33 0x00007ff7b265866e _D2rt6dmain212_d_run_main2UAAamPUQgZiZ7tryExecMFMDFZvZv D:\a\ldc\ldc\runtime\druntime\src\rt\dmain2.d:467:0
#34 0x00007ff7b2658766 _D2rt6dmain212_d_run_main2UAAamPUQgZiZ6runAllMFZv D:\a\ldc\ldc\runtime\druntime\src\rt\dmain2.d:506:0
#35 0x00007ff7b265866e _D2rt6dmain212_d_run_main2UAAamPUQgZiZ7tryExecMFMDFZvZv D:\a\ldc\ldc\runtime\druntime\src\rt\dmain2.d:467:0
#36 0x00007ff7b2658064 _d_run_main2 D:\a\ldc\ldc\runtime\druntime\src\rt\dmain2.d:529:0
#37 0x00007ff7b265859b _d_wrun_main D:\a\ldc\ldc\runtime\druntime\src\rt\dmain2.d:375:0
#38 0x00007ff7b2838f93 args::forwardToDruntime(int, wchar_t const **) F:\Development\ldc\driver\args.cpp:82:0
#39 0x00007ff7b2743c0e wmain F:\Development\ldc\driver\main.cpp:1116:0
#40 0x00007ff7b7ff65a4 invoke_main D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:90:0
#41 0x00007ff7b7ff65a4 __scrt_common_main_seh D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288:0
#42 0x00007ff8733c257d (C:\Windows\System32\KERNEL32.DLL+0x1257d)
#43 0x00007ff873acaa58 (C:\Windows\SYSTEM32\ntdll.dll+0x5aa58)```
I tried compiling with this and it was still giving the same error. Also, changing the function name to the Wasm_CXX
__gxx_wasm_personality_v0 name caused an infinite loop.
[..]
.Case("rust_eh_personality", EHPersonality::Rust)
.Case("__gxx_wasm_personality_v0", EHPersonality::Wasm_CXX)
.Case("_d_eh_personality", EHPersonality::DLang)
.Case("__xlcxx_personality_v1", EHPersonality::XL_CXX)
.Default(EHPersonality::Unknown);
[..]
case EHPersonality::Wasm_CXX:
return "__gxx_wasm_personality_v0";
case EHPersonality::DLang:
return "_d_eh_personality";
case EHPersonality::XL_CXX:
return "__xlcxx_personality_v1";
case EHPersonality::Unknown:
[..]
/// Returns true if this personality uses scope-style EH IR instructions:
/// catchswitch, catchpad/ret, and cleanuppad/ret.
inline bool isScopedEHPersonality(EHPersonality Pers) {
switch (Pers) {
case EHPersonality::MSVC_CXX:
case EHPersonality::MSVC_X86SEH:
case EHPersonality::MSVC_TableSEH:
case EHPersonality::CoreCLR:
case EHPersonality::Wasm_CXX:
case EHPersonality::DLang:
return true;
default:
return false;
}
llvm_unreachable("invalid enum");
}
/// Return true if this personality may be safely removed if there
/// are no invoke instructions remaining in the current function.
inline bool isNoOpWithoutInvoke(EHPersonality Pers) {
switch (Pers) {
case EHPersonality::Unknown:
case EHPersonality::DLang:
return false;
// All known personalities currently have this behavior
default:
return true;
}
llvm_unreachable("invalid enum");
}
More debug info:
Type-legalized selection DAG: %bb.3 '_start:'
SelectionDAG has 4 nodes:
t0: ch,glue = EntryToken
t3: ch = CopyToReg t0, Register:i32 %6, Constant:i32<1>
Legalizing: t3: ch = CopyToReg t0, Register:i32 %6, Constant:i32<1>
Trying custom legalization
Could not custom legalize node
Trying to expand node
Cannot expand node
Trying to convert node to libcall
Could not convert node to libcall
Legalizing: t2: i32 = Register %6
Legalizing: t1: i32 = Constant<1>
Legal node: nothing to do
Legalizing: t0: ch,glue = EntryToken
Legal node: nothing to do
Legalized selection DAG: %bb.3 '_start:'
SelectionDAG has 4 nodes:
t0: ch,glue = EntryToken
t3: ch = CopyToReg t0, Register:i32 %6, Constant:i32<1>
Legalizing: t3: ch = CopyToReg t0, Register:i32 %6, Constant:i32<1>
Trying custom legalization
Could not custom legalize node
Trying to expand node
Cannot expand node
Trying to convert node to libcall
Could not convert node to libcall
Combining: t3: ch = CopyToReg t0, Register:i32 %6, Constant:i32<1>
Legalizing: t2: i32 = Register %6
Combining: t2: i32 = Register %6
Legalizing: t1: i32 = Constant<1>
Legal node: nothing to do
Combining: t1: i32 = Constant<1>
Legalizing: t0: ch,glue = EntryToken
Legal node: nothing to do
Combining: t0: ch,glue = EntryToken
Optimized legalized selection DAG: %bb.3 '_start:'
SelectionDAG has 4 nodes:
t0: ch,glue = EntryToken
t3: ch = CopyToReg t0, Register:i32 %6, Constant:i32<1>
===== Instruction selection begins: %bb.3 ''
ISEL: Starting selection on root node: t3: ch = CopyToReg t0, Register:i32 %6, Constant:i32<1>
ISEL: Starting selection on root node: t2: i32 = Register %6
ISEL: Starting selection on root node: t1: i32 = Constant<1>
ISEL: Starting pattern match
Initial Opcode index to 14527
TypeSwitch[i32] from 14528 to 14531
Creating constant: t4: i32 = TargetConstant<1>
Morphed node: t1: i32 = CONST_I32 TargetConstant:i32<1>
ISEL: Match complete!
ISEL: Starting selection on root node: t0: ch,glue = EntryToken
===== Instruction selection ends:
Selected selection DAG: %bb.3 '_start:'
SelectionDAG has 5 nodes:
t0: ch,glue = EntryToken
t1: i32 = CONST_I32 TargetConstant:i32<1>
t3: ch = CopyToReg t0, Register:i32 %6, t1
********** List Scheduling %bb.3 '' **********
SU(0): t3: ch = CopyToReg t0, Register:i32 %6, t1
# preds left : 1
# succs left : 0
# rdefs left : 0
Latency : 1
Depth : 1
Height : 0
Predecessors:
SU(1): Data Latency=1
SU(1): t1: i32 = CONST_I32 TargetConstant:i32<1>
# preds left : 0
# succs left : 1
# rdefs left : 1
Latency : 1
Depth : 0
Height : 1
Successors:
SU(0): Data Latency=1
Examining Available:
Height 0: SU(0): t3: ch = CopyToReg t0, Register:i32 %6, t1
*** Scheduling [0]: SU(0): t3: ch = CopyToReg t0, Register:i32 %6, t1
Examining Available:
Height 1: SU(1): t1: i32 = CONST_I32 TargetConstant:i32<1>
*** Scheduling [1]: SU(1): t1: i32 = CONST_I32 TargetConstant:i32<1>
*** Final schedule ***
SU(1): t1: i32 = CONST_I32 TargetConstant:i32<1>
SU(0): t3: ch = CopyToReg t0, Register:i32 %6, t1
FastISel missed (in function: _start)
Assertion failed: R == 0 && "Already initialized this value register!", file F:\Development\llvm-project\llvm\include\llvm/CodeGen/FunctionLoweringInfo.h,
line 222
When changing to the __gxx_wasm_personality_v0 function, the infinite loop is on the EHPadBB while:
static void findWasmUnwindDestinations(
FunctionLoweringInfo &FuncInfo, const BasicBlock *EHPadBB,
BranchProbability Prob,
SmallVectorImpl<std::pair<MachineBasicBlock *, BranchProbability>>
&UnwindDests) {
while (EHPadBB) {
const Instruction *Pad = EHPadBB->getFirstNonPHI();
if (isa<CleanupPadInst>(Pad)) {
// Stop on cleanup pads.
UnwindDests.emplace_back(FuncInfo.MBBMap[EHPadBB], Prob);
UnwindDests.back().first->setIsEHScopeEntry();
break;
} else if (const auto *CatchSwitch = dyn_cast<CatchSwitchInst>(Pad)) {
// Add the catchpad handlers to the possible destinations. We don't
// continue to the unwind destination of the catchswitch for wasm.
for (const BasicBlock *CatchPadBB : CatchSwitch->handlers()) {
UnwindDests.emplace_back(FuncInfo.MBBMap[CatchPadBB], Prob);
UnwindDests.back().first->setIsEHScopeEntry();
}
break;
} else {
continue;
}
}
}
Seems to be fixed in 1.36.0
nevermind I didn't have the proper compile flag when testing (has to be in lflags too for dub now)
I tried compiling a simple try/catch wasm32-unknown-wasi .d file with --wasm-enable-eh and I get a crash while writing the object file. Is it supported currently?
Thanks