[clang] [CIR] Add CIRGen for cir.unreachable and cir.trap (PR #151363)
Sirui Mu via cfe-commits
cfe-commits at lists.llvm.org
Thu Jul 31 08:54:54 PDT 2025
================
@@ -269,6 +270,22 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID,
case Builtin::BI__builtin_rotateright32:
case Builtin::BI__builtin_rotateright64:
return emitRotate(e, /*isRotateLeft=*/false);
+
+ case Builtin::BI__builtin_trap: {
+ builder.create<cir::TrapOp>(loc);
+ // Note that cir.trap is a terminator so we need to start a new dummy block
+ // to preserve the builder's insertion point.
+ builder.createBlock(builder.getBlock()->getParent());
----------------
Lancern wrote:
> Also is this really needed? Classic codegen adds additional block only for unreachable.
In the classic CodeGen, calls to `__builtin_unreachable` gets lowered to the `unreachable` instruction, and calls to `__builtin_trap` gets lowered to an intrinsic call to `@llvm.trap()`. The former is a terminator instruction, which prehibits any further instructions from following it in the same block. The latter is not a terminator and it could be followed by more instructions in the same block (these instructions would be DCE-ed however). So in the classic CodeGen we don't have to start a new block after calling `__builtin_trap`.
On the contrary, in CIR world, both of `cir.unreachable` and `cir.trap` are terminators. Thus we have to start a new block after them to hold those instructions that follow them.
> Also it is unclear to me why this one is inlined while unreachable uses emitUnreachable as in classic codegen. We should probably add emitTrap too.
`emitUnreachable` is there because we have a sanitifer for unreachable code. We don't have sanitizers for traps, so we just inlined the creation of `cir.trap`.
Maybe we could put `builder.createBlock` in `emitUnreachable` and `emitTrap` though.
https://github.com/llvm/llvm-project/pull/151363
More information about the cfe-commits
mailing list