Skip to content

Exceptions cause crash in LLVM #121

Description

@TurkeyMan

Checklist

  • Checked the issue tracker for similar issues to ensure this is not a duplicate
  • Read the documentation to confirm the issue is not addressed there and your configuration is set correctly
  • Tested with the latest version to ensure the issue hasn't been fixed

How often does this bug occurs?

always

Expected behavior

LLVM shouldn't crash when I write a try/catch block.

Actual behavior (suspected bug)

I've been trying out the xtensa backend in LDC (built against LLVM21), but exceptions cause LLVM to crash when any optimisation level is enabled.

If I add a try/catch block, it compiles, but then I add -O1 and a crash appears.

Error logs or terminal output

It's just an ICE, nothing diagnostic.

Steps to reproduce the behavior

I'm using ldc2, built against LLVM21, this code causes the crash:

ldc2 -mtriple=xtensa-none-elf -mattr=+density,+mul16,+mul32,+div32,+windowed -O1 -c
module xtensa_eh_crash;

void external_call(int delegate(const(char)[], int) dg);

int opApply(int delegate(const(char)[], int) dg)
{
    int result;
    try
    {
        external_call(dg);
    }
    catch (Exception e)
    {
        result = -1;
    }
    return result;
}

I tested similar code in C++ using ESP-IDF's Clang, and I noticed that the compiler doesn't crash like this, but there's just no EH material in the output binary at all; as if it just dropped it completely or didn't even try. I guess it would abort instantly on throw?

Project release version

LLVM21

System architecture

Intel/AMD 64-bit (modern PC, older Mac)

Operating system

Linux

Operating system version

Debian

Shell

Bash

Additional context

I got Claude to poke at it for a while testing various combinations and trying to dig out any detail, this is what he came up with:


Any function with an invoke + landingpad will trigger this. The key pattern is: invoke that can throw → landing pad with catch clause → resume path.

MIR Evidence
The landing pad block in the crashing function shows undefined registers:

bb.11 (%ir-block.53, landing-pad):
  EH_LABEL <mcsymbol >
  %17:ar = COPY %33:ar     ← %33 never defined anywhere
  BEQI %34:ar, 1, %bb.9%34 never defined anywhere

Compare to working backends (x86, ARM) where %33/%34 would be defined by the ISel lowering of the landingpad instruction's {ptr, i32} result.

Likely Fix Location
The Xtensa ISel lowering likely needs to handle ISD::EH_RETURN / exception handling register setup in XtensaTargetLowering::LowerOperation() or similar, defining the exception pointer and selector registers in the landing pad entry. Most backends do this via getExceptionPointerRegister() / getExceptionSelectorRegister() in their TargetLowering class.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions