#9576·ghidra

sleigh silently accepts constructors whose patterns cannot be distinguished, unless -l is passed

Author: cwright7101Created Sep 2, 2026Updated Sep 14, 2026
LabelsFeature: SleighStatus: Internal

Describe the bug

When two constructors have patterns that overlap without being identical, sleigh builds the language without a word of complaint and picks a winner. The conflict is only reported if you pass -l, and then it is an error that stops the build.

The default is set in the SleighCompile constructor:

lenientconflicterrors = true;

and the errors are gated on it:

if (!lenientconflicterrors) {
    VectorSTL<String> cerrors = props.getConflictErrors();
    for (int i = 0; i < cerrors.size(); ++i) {
        errors += 1;
        Msg.error(this, cerrors.get(i));
    }
}

Identical patterns go through getIdentErrors(), which is not gated, so those are always reported. It is specifically the overlapping case that is silent.

I understand the leniency is deliberate — real specs would be painful to write if every overlap were fatal. What I would like to change is that the default is silent, not that it is permissive. As things stand you can develop a whole processor module, never pass -l, and never learn that some of your instructions are decoded by whichever constructor happened to win. That is what happened to me across four GPU ISA modules: none of them could build under -l, so every .sla that had ever shipped from them was built with conflicts resolved arbitrarily, and nothing had ever said so.

The failure is quiet in the worst way — the grammar works, it just sometimes decodes to the wrong instruction, and the wrong one is a legitimate constructor from your own spec.

To Reproduce

  1. conflict2.slaspec:

    define endian=little;
    define alignment=1;
    define space ram      type=ram_space      size=4 default;
    define space register type=register_space size=4;
    define register offset=0 size=4 [ r0 r1 ];
    
    define token instr(8)
      opc = (0,3)
      xx  = (4,7)
    ;
    
    # Patterns overlap but are not identical: the byte 0x21 matches both.
    :"FOO" is opc=1 { r0 = 1; }
    :"BAR" is xx=2  { r0 = 2; }
    
  2. sleigh -e conflict2.slaspec

    Produces conflict2.sla. No warning, no error, no mention of the overlap.

  3. sleigh -l -e conflict2.slaspec

    ERROR conflict2.slaspec:14: Constructor patterns cannot be distinguished:
       InstructionPattern{0010....} table "instruction" constructor from conflict2.slaspec:14
       InstructionPattern{....0001} table "instruction" constructor from conflict2.slaspec:13
    ERROR No output produced
    
  4. Load the .sla from step 2 and disassemble the byte 0x21, which satisfies both patterns. It comes back as FOO. Which of the two wins is not something the spec author chose or was told about.

Expected behavior

Report the conflicts by default, as warnings, and keep -l as the switch that promotes them to errors. A spec author would then see

WARN conflict2.slaspec:14: Constructor patterns cannot be distinguished: ...

on an ordinary build, and could decide whether each one is intentional. Nothing that currently compiles would stop compiling.

If changing the default is too disruptive, a one-line summary at the end of a build — 12 constructor pattern conflicts resolved arbitrarily; run with -l for detail — would be enough to stop this being invisible.

Screenshots

N/A.

Attachments

The full spec is inline above.

Environment (please complete the following information):

  • OS: Ubuntu 22.04.5 LTS (kernel 5.15.0-190)
  • Java Version: OpenJDK 21.0.12
  • Ghidra Version: 12.1.3 (build 2026-Aug-17)
  • Ghidra Origin: official GitHub distro

Additional context

I appreciate this may be working as designed, in which case treat it as a request to make the default louder rather than stricter. The reason I think it is worth changing is the asymmetry: the cost of a spurious warning is that someone reads a line of build output, and the cost of the current silence is a grammar that decodes some instructions as the wrong instruction with no indication anywhere that a choice was made.

Source: NationalSecurityAgency/ghidra