[CIR] Lower aligned operator new in CIRGen (and matching cleanup-during-new) (#197094)
Two related `errorNYI`s in CIRGen for C++17 aligned `operator new` /
`delete`:
- `emitCXXNewExpr` `errorNYI`'d on `"emitCXXNewExpr: pass alignment"`
when the allocator is the `align_val_t`-overloaded form (called whenever
you `new` an over-aligned type).
- The cleanup-during-new path (the `CallDeleteDuringNew` cleanup that
fires if a ctor throws after `operator new` returns) `errorNYI`'d on the
matching `"CallDeleteDuringNew: aligned allocation"`.
The non-cleanup delete path was already wired up; this just plumbs the
matching new side.
Both fixes are direct ports of `clang/lib/CodeGen/CGExprCXX.cpp`. In
`emitCXXNewExpr` we look up the alignment parameter type from the
allocator prototype (or fall back to `size_t` for the variadic corner
case classic also handles), build a constant of that type, and append it
after the size argument. The cleanup uses `getSizeType()` for the
alignment param type per the existing `// FIXME` comment that's also in
classic.
Hit this trying to build `706.stockfish_r` from SPEC CPU 2026 with
`-fclangir` — stockfish allocates over-aligned NNUE state via plain
`new`. The minimum repro:
```c++
struct alignas(64) Big { char data[64]; };
void f() { Big *p = new Big; delete p; }
```
The new test cross-checks against OGCG so any drift between the two
backends shows up — both emit the same `_ZnwmSt11align_val_t(64, 64)`
and `_ZdlPvmSt11align_val_t(p, 64, 64)` calls.
A few honest caveats worth flagging:
- The `CallDeleteDuringNew` fix isn't directly exercised by the test.
Triggering it needs `-fcxx-exceptions` plus a throwing ctor, and CIR's
EH path has its own NYIs that would muddy the test. The cleanup is a 1:1
mirror of the regular-delete-side fix that already landed and uses the
same `getSizeType()` fallback as classic.
- The variadic `operator new(size_t, ...)` corner case is also untested.
The `if (allocatorType->getNumParams() > paramsToSkip)` branch covers
the common case; the else branch falls back to `sizeType` (mirroring
classic, which guards the equivalent with
`assert(allocator->isVariadic())` and likewise has no test).
- The cleanup path uses `getSizeType()` for the alignment param type
rather than the actual `align_val_t` enum, mirroring the existing `//
FIXME` in classic. ABI-equivalent — `align_val_t`'s underlying type is
`size_t` — but the IR type label differs.
Both CIR test suites pass cleanly (`check-clang-cir-codegen` 325/326 + 1
unsupported, `check-clang-cir` 718/729 + 1 XFAIL + 10 unsupported).Welcome to the LLVM project!
This repository contains the source code for LLVM, a toolkit for the construction of highly optimized compilers, optimizers, and run-time environments.
The LLVM project has multiple components. The core of the project is itself called “LLVM”. This contains all of the tools, libraries, and header files needed to process intermediate representations and convert them into object files. Tools include an assembler, disassembler, bitcode analyzer, and bitcode optimizer.
C-like languages use the Clang frontend. This component compiles C, C++, Objective-C, and Objective-C++ code into LLVM bitcode -- and from there into object files, using LLVM.
Other components include: the libc++ C++ standard library, the LLD linker, and more.
Consult the Getting Started with LLVM page for information on building and running LLVM.
For information on how to contribute to the LLVM project, please take a look at the Contributing to LLVM guide.
Join the LLVM Discourse forums, Discord chat, LLVM Office Hours or Regular sync-ups.
The LLVM project has adopted a code of conduct for participants to all modes of communication within the project.