[BPF] Check every locked atomic insn for a used result (#231550)
With `-mcpu=v3` and later, a monotonic (relaxed) `atomicrmw add`, `sub`,
`and`,
`or` or `xor` whose result is used is selected to the locked insn, which
does
not return the old value, so the program gets the operand register back
instead. The verifier accepts the program and it silently computes the
wrong
value: `next()` below returns 1 on every call instead of the previous
value of
`counter`, so anything built on it, such as an id or sequence counter,
breaks
without any error at compile or load time.
```c
long counter;
long next(void) {
return __atomic_fetch_add(&counter, 1, __ATOMIC_RELAXED);
[50 lines not shown]
[CIR][OpenMP] Add support for the OpenMP 'for' directive
This patch adds support for wsloop in ClangIR: the `for` directive and its
combined forms `parallel for` and `target parallel for`. This is lowered to an
omp.wsloop + omp.loop_nest, nested utilizing the existing queue-based
decomposition.
Assisted-by: Cursor / Claude Sonnet 5 High
[ValueTracking] Address plus in-object offset is never null (#231649)
LangRef guarantees that no allocated object crosses the unsigned address
space boundary, including the address one past its end, so a non-zero
offset that stays within an object cannot produce the null address, even
if the object starts at zero. Teach isNonZeroAdd about this, taking the
size from getPointerDereferenceableBytes so that globals, allocas and
dereferenceable arguments are covered; previously this was only provable
when the object's alignment supplied low zero bits. The address may be a
ptrtoaddr, or a ptrtoint at least as wide as the address.
simplifyICmpInst returns whatever ConstantFoldCompareInstOperands gives
for two constants, including nullptr, so a comparison between constants
never reaches the generic logic below. Fall through in that case. That
exposes two gaps in isKnownNonZero: it reported a GlobalAlias as non
null, contradicting evaluateICmpRelation's deliberate refusal to decide
alias comparisons (PR1646), and it reported a global as non null even
where null is a valid address. Exclude aliases and use
NullPointerIsDefined(), which subsumes the address space check.
[5 lines not shown]
[clang][Driver] Use the Windows ARM64 defaults for aarch64-unknown-uefi
Match the Windows ARM64 driver defaults for aarch64-unknown-uefi, which
follows the same ABI:
* char is signed, so do not pass -fno-signed-char,
* the frame chain must stay valid even when frame pointers are omitted,
so -fomit-frame-pointer yields -mframe-pointer=reserved rather than
none, as the backend reserves the frame pointer for UEFI as well,
* -msign-return-address selects the B key, the only one the backend
accepts for Windows and UEFI.
Assisted-by: Claude
[clang] Add aarch64-unknown-uefi target
Add the aarch64-unknown-uefi target to clang, building on the backend
support added in the preceding patches. Like x86_64-unknown-uefi it
follows the Microsoft ABI conventions, matching the Windows ARM64 target
which is the only way EFI applications for AArch64 can be built with
Clang/LLVM today:
* add UEFIAArch64TargetInfo: LLP64 types, Microsoft C++ ABI, char*
based va_list and the Win64 calling convention kind,
* use the Windows AArch64 ABI info in CodeGen for UEFI,
* accept aarch64 for *-uefi triples in the driver.
The UEFI toolchain already handles the linker invocation (lld-link with
/subsystem:efi_application), so no further driver changes are needed.
Assisted-by: Claude
[AArch64] Apply the Windows SEH and CRT codegen constraints to UEFI
aarch64-unknown-uefi uses SEH unwind information and has no C runtime
library, so the remaining Windows specific codegen decisions that follow
from this apply to it too:
* do not align loops or basic blocks, since SEH unwind info generation
needs the exact function layout before alignment padding is inserted,
* sign return addresses with the B key by default and reject A key
signing, matching the pac_sign_lr unwind code used by the unwinder;
the branch protection parser defaults to the B key for UEFI as well,
so that -mbranch-protection=pac-ret keeps working,
* do not lower wide shifts to libcalls at -Oz, as those helpers are not
available.
The corresponding Windows tests gain aarch64-unknown-uefi run lines and
the LLVM release notes announce the new target, which completes the
backend side of aarch64-unknown-uefi support.
Assisted-by: Claude
[AArch64] Classify global references on UEFI like Windows COFF
Apply the Windows COFF rules for global references to
aarch64-unknown-uefi, which produces the same PE/COFF images:
* classify dllimport and non-dso-local globals with MO_DLLIMPORT /
MO_COFFSTUB, so extern_weak symbols are referenced through a stub that
can be resolved to zero by the linker,
* keep the existing SelectionDAG, FastISel and GlobalISel handling of
calls and tail calls to extern_weak functions in sync with that,
* default to the PIC relocation model, so jump tables and other
references stay position independent in relocatable PE images,
* lower ifuncs on UEFI as COFF has no support for them.
The extern weak and jump table tests gain aarch64-unknown-uefi run lines,
and a new test checks that the default pipelines lower ifuncs for both
Windows and UEFI.
Assisted-by: Claude
[CIR] Honor C++17 operator-call argument evaluation order (#232779)
C++17 (P0145) sequences the right operand of an assignment before the
left, even when the assignment resolves to an overloaded operator. CIR
did not apply this to non-member operators.
CIRGenFunction::emitCall now selects the evaluation order by following
faithfully OG.
The OG changes target code sharing, and for OG those should be NFC.
The new test now is mostly a copy off `CodeGenCXX/cxx1z-eval-order.cpp`
to CIR. The MS ABI RUN lines are dropped.
[GlobalISel] Honor the disable-tail-calls attribute for libcalls (#233404)
GlobalISel lowered libcalls as tail calls even when the caller had
`"disable-tail-calls"="true"`.
Check the attribute in isLibCallInTailPosition so such libcalls are not
tail called.
[CIR] Reject language address spaces in DirectToLLVM pointer conversion
Reject unlowered language address spaces in pointer types when bypassing TargetLowering. Guard pointer-producing lowerings, including generated patterns, so failed conversions report legalization failures instead of silently selecting address space zero or constructing invalid LLVM operations.
Assisted-by: Codex / GPT-6
fix: [CIR] Check only the converted pointer's address space
Limit opaque pointer conversion to its own address space and diagnose unsupported pointee types where their layout is required. Emit type-specific errors for failed pointer conversions.
Validate pointee memory conversion before deriving copy sizes, alignments, or pointer-difference strides from CIR layout. Keep deeper pointee types opaque when their layouts are not needed.
Assisted-by: Codex / GPT-6
[CIR] Propagate initializer type adjustment failures
Reject initializers whose active members have no LLVM representation, including when an enclosing union's storage type is convertible. Propagate recursive adjustment failures before querying data layout or constructing LLVM operations.
Assisted-by: Codex / GPT-6
fix: [CIR] Diagnose unsupported type conversions
Emit NYI diagnostics naming the unsupported type and include symbol context when available.
Assisted-by: Codex / GPT-6
[CIR] Propagate type conversion failures in DirectToLLVM
Propagate failed type and constant conversions through DirectToLLVM so unsupported types produce legalization failures instead of invalid LLVM operations or a void function result.
Assisted-by: Codex / GPT-6
[Clang][counted_by] Don't re-evaluate the base of a counted_by pointer access for -fsanitize=array-bounds
When indexing a 'counted_by' pointer field with -fsanitize=array-bounds,
EmitCountedByBoundsChecking was handed an invalid address and re-emitted
the field's l-value to locate the count. That re-evaluated the struct
base, duplicating its side-effects:
struct p { int count; int *buf __counted_by(count); };
struct p *q;
int f(int i) { return q++->buf[i]; } // 'q' incremented twice
int g(int i) { return get()->buf[i]; } // 'get' called twice
i.e. enabling the sanitizer changed the program's behavior.
When the subscript base is exactly the field load, emit the field's
l-value once, load the pointer from it (as the default case of
EmitPointerWithAlignment does, through EmitLoadOfLValue so that a
'__ptrauth'-qualified field is still authenticated), and pass the
field's address to the bounds check. When there's an intervening cast (e.g.
[6 lines not shown]
[SystemZ][z/OS] Emit fill in HLASM output (#233056)
HLASM streamer never overrode emitFill and the MCStreamer
default does nothing, so anything that went through emitZeros or a splat
came out as no bytes at all. That meant zero initialised globals and
common symbols had no storage, and struct padding was dropped so an i64
after an i8 ended up at offset 1 instead of 8. The GOFF object path was
already fine, this just makes the HLASM text match it using DC nXL1'hh',
and it errors out past X'7FFFFFFF' since that's the GOFF limit for both
the duplication factor and the location counter. The PPA1 tests change
because the padding after the function name was missing from the HLASM
side too.
[compiler-rt] Remove dlsym interceptor and support `-shared-libsan` for CSan
Summary:
Follow the UBSan offload runtime. Offload now resolves HSA through the
global scope, so the `dlsym` interceptor is no longer needed. The real
HSA entry points are still taken from the loaded HSA library rather than
`RTLD_NEXT`, since every DSO with a static runtime exports the same
wrappers and they would otherwise chain back into each other.
Build `libclang_rt.csan.so` with the offload objects folded in. The
exported HSA wrappers report failure when HSA is absent and warn when HSA
was loaded ahead of the runtime. The preinit hook moves to a separate
`csan_offload-preinit` archive for executables.
[compiler-rt] Add 'csan' library for the concurrency sanitizer
Summary:
Adds the runtime for the concurrency sanitizer, both CPU and GPU.
Fundamentally, this works using the following pseudocode:
```c
static u64 watchpoints[N]; // Hash-indexed, zero is empty.
// Emitted before the access, so we never trip on our own write.
void check_access(volatile void *addr, u32 size, u32 type) {
// Every access probes. A read conflicts only with a watched write, a
// write conflicts with either.
if (u64 *wp = find_watchpoint(addr, size, type))
consume(wp, this_pc()); // Hand our location to the owner.
if (!should_sample()) // Wave-uniform, 1-in-N chance.
return;
[17 lines not shown]
[Clang] Support `-shared-libsan` for offload CSan
Summary:
Follow the UBSan handling. The shared runtime embeds the HSA
interceptors, so `csan_offload` is only linked with static runtimes and
executables pull in `csan_offload-preinit` to initialize early.
[Clang] Add support for the `-fsanitize=concurrency` runtime
Summary:
Add the frontend sanitizer kind, function attributes, pass pipeline
integration, predefined macro, driver handling, and documentation for
ConcurrencySanitizer.