Compare commits

...

165 Commits

Author SHA1 Message Date
Simon Pilgrim
2a79ef66eb
[AMDGPU] canCreateUndefOrPoisonForTargetNode - BFE_I32/U32 can't create poison/undef (#154932)
Add AMDGPUTargetLowering::canCreateUndefOrPoisonForTargetNode handler
and tag BFE_I32/U32 nodes as they can only propagate poison, not create
poison/undef.

Fighting some of the remaining regressions in #152107
2025-08-22 12:14:45 +00:00
Jungwook Park
b149fc7755
[mlir][scf] Quick fix to scf.execute_region no_inline (#154931)
Asm printer should exclude `no_inline` attr during printing optional
attrs at the bottom.
2025-08-22 13:11:27 +01:00
Michael Halkenhäuser
7c1d2467f1
Reland: [OpenMP] Add ompTest library to OpenMP (#154786)
Reland of https://github.com/llvm/llvm-project/pull/147381

Added changes to fix observed BuildBot failures:
 * CMake version (reduced minimum to `3.20`, was: `3.22`)
 * GoogleTest linking (missing `./build/lib/libllvm_gtest.a`)
* Related header issue (missing `#include
"llvm/Support/raw_os_ostream.h"`)

Original message

Description
===========
OpenMP Tooling Interface Testing Library (ompTest) ompTest is a unit testing framework for testing OpenMP implementations. It offers a simple-to-use framework that allows a tester to check for OMPT events in addition to regular unit testing code, supported by linking against GoogleTest by default. It also facilitates writing concise tests while bridging the semantic gap between the unit under test and the OMPT-event testing.

Background
==========
This library has been developed to provide the means of testing OMPT implementations with reasonable effort. Especially, asynchronous or unordered events are supported and can be verified with ease, which may prove to be challenging with LIT-based tests. Additionally, since the assertions are part of the code being tested, ompTest can reference all corresponding variables during assertion.

Basic Usage
===========
OMPT event assertions are placed before the code, which shall be tested. These assertion can either be provided as one block or interleaved with the test code. There are two types of asserters: (1) sequenced "order-sensitive" and (2) set "unordered" assserters. Once the test is being run, the corresponding events are triggered by the OpenMP runtime and can be observed. Each of these observed events notifies asserters, which then determine if the test should pass or fail.

Example (partial, interleaved)
==============================
```c++
  int N = 100000;
  int a[N];
  int b[N];

  OMPT_ASSERT_SEQUENCE(Target, TARGET, BEGIN, 0);
  OMPT_ASSERT_SEQUENCE(TargetDataOp, ALLOC, N * sizeof(int)); // a ?
  OMPT_ASSERT_SEQUENCE(TargetDataOp, H2D, N * sizeof(int), &a);
  OMPT_ASSERT_SEQUENCE(TargetDataOp, ALLOC, N * sizeof(int)); // b ?
  OMPT_ASSERT_SEQUENCE(TargetDataOp, H2D, N * sizeof(int), &b);
  OMPT_ASSERT_SEQUENCE(TargetSubmit, 1);
  OMPT_ASSERT_SEQUENCE(TargetDataOp, D2H, N * sizeof(int), nullptr, &b);
  OMPT_ASSERT_SEQUENCE(TargetDataOp, D2H, N * sizeof(int), nullptr, &a);
  OMPT_ASSERT_SEQUENCE(TargetDataOp, DELETE);
  OMPT_ASSERT_SEQUENCE(TargetDataOp, DELETE);
  OMPT_ASSERT_SEQUENCE(Target, TARGET, END, 0);

#pragma omp target parallel for
  {
    for (int j = 0; j < N; j++)
      a[j] = b[j];
  }
```

References
==========
This work has been presented at SC'24 workshops, see: https://ieeexplore.ieee.org/document/10820689

Current State and Future Work
=============================
ompTest's development was mostly device-centric and aimed at OMPT device callbacks and device-side tracing. Consequentially, a substantial part of host-related events or features may not be supported in its current state. However, we are confident that the related functionality can be added and ompTest provides a general foundation for future OpenMP and especially OMPT testing. This PR will allow us to upstream the corresponding features, like OMPT device-side tracing in the future with significantly reduced risk of introducing regressions in the process.

Build
=====
ompTest is linked against LLVM's GoogleTest by default, but can also be built 'standalone'. Additionally, it comes with a set of unit tests, which in turn require GoogleTest (overriding a standalone build). The unit tests are added to the `check-openmp` target.

Use the following parameters to perform the corresponding build: 
`LIBOMPTEST_BUILD_STANDALONE` (Default: ${OPENMP_STANDALONE_BUILD})
`LIBOMPTEST_BUILD_UNITTESTS` (Default: OFF)

---------

Co-authored-by: Jan-Patrick Lehr <JanPatrick.Lehr@amd.com>
Co-authored-by: Joachim <protze@rz.rwth-aachen.de>
Co-authored-by: Joachim Jenke <jenke@itc.rwth-aachen.de>
2025-08-22 13:56:12 +02:00
Leandro Lacerda
15a192cde5
[libc] Enable double math functions on the GPU (#154857)
This patch adds the `acos` math function to the NVPTX build. It also
adds the `sincos` math function to the `math.h` header.
2025-08-22 06:52:13 -05:00
paperchalice
2014890c09
[SelectionDAG] Remove UnsafeFPMath in visitFP_ROUND (#154768)
Remove `UnsafeFPMath` in `visitFP_ROUND` part, it blocks some bugfixes
related to clang and the ultimate goal is to remove `resetTargetOptions`
method in `TargetMachine`, see FIXME in `resetTargetOptions`.
See also
https://discourse.llvm.org/t/rfc-honor-pragmas-with-ffp-contract-fast

https://discourse.llvm.org/t/allowfpopfusion-vs-sdnodeflags-hasallowcontract

Now all UnsafeFPMath uses are eliminated in LLVMCodeGen
2025-08-22 19:46:33 +08:00
Simon Pilgrim
d8769bb5b7 [AMDGPU] bf16-conversions.ll - regenerate checks
Reduce diffs in #152107
2025-08-22 12:20:50 +01:00
Lang Hames
3292edb7b4
[orc-rt] Add C and C++ APIs for WrapperFunctionResult. (#154927)
orc_rt_WrapperFunctionResult is a byte-buffer with inline storage and a
builtin error state. It is intended as a general purpose return type for
functions that return a serialized result (e.g. for communication across
ABIs or via IPC/RPC).

orc_rt_WrapperFunctionResult contains a small amount of inline storage,
allowing it to avoid heap-allocation for small return types (e.g. bools,
chars, pointers).
2025-08-22 21:18:30 +10:00
Mehdi Amini
d2b810e24f [MLIR] Apply clang-tidy fixes for readability-identifier-naming in DataFlowFramework.cpp (NFC) 2025-08-22 04:12:50 -07:00
Mehdi Amini
a8aacb1b66 [MLIR] Apply clang-tidy fixes for misc-use-internal-linkage in toy Tutorial (NFC) 2025-08-22 04:12:50 -07:00
Mehdi Amini
d2dee948a4 [MLIR] Improve clang-tidy script
This just helping to better keep track of the failures.
2025-08-22 04:12:50 -07:00
Jacek Caban
a6fcd1a663
[LLD][COFF] Set isUsedInRegularObj for target symbols in resolveAlternateNames (#154837)
Fixes: #154595

Prior to commit bbc8346e6bb543b0a87f52114fed7d766446bee1, this flag was
set by `insert()` from `addUndefined()`. Set it explicitly now.
2025-08-22 13:05:19 +02:00
Ramkumar Ramachandra
2975e674ec
[VPlan] Improve style in match_combine_or (NFC) (#154793) 2025-08-22 12:01:42 +01:00
Hans Wennborg
ee5367bedb Revert "[compiler-rt]: fix CodeQL format-string warnings via explicit casts (#153843)"
It broke the build:

compiler-rt/lib/hwasan/hwasan_thread.cpp:177:11: error: unknown type name 'ssize_t'; did you mean 'size_t'?
   177 |          (ssize_t)unique_id_, (void *)this, (void *)stack_bottom(),
       |           ^~~~~~~
       |           size_t

> This change addresses CodeQL format-string warnings across multiple
> sanitizer libraries by adding explicit casts to ensure that printf-style
> format specifiers match the actual argument types.
>
> Key updates:
> - Cast pointer arguments to (void*) when used with %p.
> - Use appropriate integer types and specifiers (e.g., size_t -> %zu,
> ssize_t -> %zd) to avoid mismatches.
> - Fix format specifier mismatches across xray, memprof, lsan, hwasan,
> dfsan.
>
> These changes are no-ops at runtime but improve type safety, silence
> static analysis warnings, and reduce the risk of UB in variadic calls.

This reverts commit d3d5751a39452327690b4e011a23de8327f02e86.
2025-08-22 12:50:53 +02:00
Lang Hames
d5af08a221
[orc-rt] Add inline specifier to orc_rt::make_error. (#154922)
Prevents linker errors for duplicate definitions when make_error is used
from more than one file.
2025-08-22 20:37:10 +10:00
nerix
d6fcaef281
[LLDB][Value] Require type size when reading a scalar (#153386)
When reading a value as a scalar, the type size is required. It's
returned as a `std::optional`. This optional isn't checked for scalar
values, where it is unconditionally accessed.

This came up in the
[Shell/Process/Windows/msstl_smoke.cpp](4e10b62442/lldb/test/Shell/Process/Windows/msstl_smoke.cpp)
test. There, LLDB breaks at the function entry, so all locals aren't
initialized yet. Most values will contain garbage. The [`std::list`
synthetic
provider](4e10b62442/lldb/source/Plugins/Language/CPlusPlus/GenericList.cpp (L517))
tries to read the value using `GetData`. However, in
[`ValueObject::GetData`](4e10b62442/lldb/source/ValueObject/ValueObject.cpp (L766)),
[`ValueObjectChild::UpdateValue`](88c993fbc5/lldb/source/ValueObject/ValueObjectChild.cpp (L102))
fails because the parent already failed to read its data, so `m_value`
won't have a compiler type, thus the size can't be read.
2025-08-22 12:26:03 +02:00
Ross Brunton
17dbb92612
[Offload][NFC] Use tablegen names rather than name parameter for API (#154736) 2025-08-22 11:13:57 +01:00
tangaac
8439777131
[LoongArch] Pre-commit tests for vecreduce_and/or/... (#154879) 2025-08-22 17:52:43 +08:00
YafetBeyene
fda24dbc16
[BOLT] Add dump-dot-func option for selective function CFG dumping (#153007)
## Change:
* Added `--dump-dot-func` command-line option that allows users to dump
CFGs only for specific functions instead of dumping all functions (the
current only available option being `--dump-dot-all`)

## Usage:
* Users can now specify function names or regex patterns (e.g.,
`--dump-dot-func=main,helper` or `--dump-dot-func="init.*`") to generate
.dot files only for functions of interest
* Aims to save time when analysing specific functions in large binaries
(e.g., only dumping graphs for performance-critical functions identified
through profiling) and we can now avoid reduce output clutter from
generating thousands of unnecessary .dot files when analysing large
binaries

## Testing
The introduced test `dump-dot-func.test` confirms the new option does
the following:

- [x] 1. `dump-dot-func` can correctly filter a specified functions
- [x] 2. Can achieve the above with regexes
- [x] 3. Can do 1. with a list of functions
- [x] No option specified creates no dot files
- [x] Passing in a non-existent function generates no dumping messages
- [x] `dump-dot-all` continues to work as expected
2025-08-22 10:51:09 +01:00
Ivan Kosarev
7594b4b8d1 [AMDGPU] Fix compilation errors. 2025-08-22 10:30:43 +01:00
Abhinav Garg
bfc16510c7
[AMDGPU] Regenerate test case to cover gfx10 check lines. (#154909)
Check lines for GFX10 is missing in this test case. Regenerate to fix
test case.
2025-08-22 15:00:28 +05:30
Nikolas Klauser
fd52f4d232
[libc++][NFC] Simplify the special member functions of the node containers (#154707)
This patch does two things:
- Remove exception specifications of `= default`ed special member
functions
- `= default` special member functions

The first part is NFC because the explicit specification does exactly
the same as the implicit specification. The second is NFC because it
does exactly what the `= default`ed special member does.
2025-08-22 11:24:28 +02:00
Florian Hahn
8bc038daf2
[InstComb] Allow more user for (add (ptrtoint %B), %O) to GEP transform. (#153566)
Generalize the logic from
https://github.com/llvm/llvm-project/pull/153421 to support additional
cases where the pointer is only used as integer.

Alive2 Proof: https://alive2.llvm.org/ce/z/po58pP

This enables vectorizing std::find for some cases, if additional
assumptions are provided: https://godbolt.org/z/94oq3576E

Depends on https://github.com/llvm/llvm-project/pull/15342.

PR: https://github.com/llvm/llvm-project/pull/153566
2025-08-22 10:17:12 +01:00
Ivan Kosarev
faca8c9ed4
[AMDGPU][NFC] Only include CodeGenPassBuilder.h where needed. (#154769)
Saves around 125-210 MB of compilation memory usage per source for
roughly one third of our backend sources, ~60 MB on average.
2025-08-22 10:05:06 +01:00
Simon Pilgrim
1b4fe26343
[clang][x86] Add release note entries describing recent work to making SSE intrinsics generic and usable with constexpr (#154737)
I haven't created an exhaustive list of intrinsic changes, but I suppose I could if people see a strong need for it.
2025-08-22 09:59:10 +01:00
Baranov Victor
00a405f666
[clang-tidy][NFC] Fix "llvm-prefer-static-over-anonymous-namespace" warnings 1/N (#153885) 2025-08-22 11:54:17 +03:00
Hans Wennborg
8bf105cb01
[asan] Build the Windows runtime with /hotpatch (#154694)
Win/ASan relies on the runtime's functions being 16-byte aligned so it
can intercept them with hotpatching. This used to be true (but not
guaranteed) until #149444.

Passing /hotpatch will give us enough alignment and generally ensure
that the functions are hotpatchable.
2025-08-22 10:40:04 +02:00
Bjorn Pettersson
2d3167f8d8
[SeparateConstOffsetFromGEP] Avoid miscompiles related to trunc nuw/nsw (#154582)
Drop poison generating flags on trunc when distributing trunc over
add/sub/or. We need to do this since for example
(add (trunc nuw A), (trunc nuw B)) is more poisonous than
(trunc nuw (add A, B))).

In some situations it is pessimistic to drop the flags. Such as
if the add in the example above also has the nuw flag. For now we
keep it simple and always drop the flags.

Worth mentioning is that we drop the flags when cloning
instructions and rebuilding the chain. This is done after the
"allowsPreservingNUW" checks in ConstantOffsetExtractor::Extract.
So we still take the "trunc nuw" into consideration when determining
if nuw can be preserved in the gep (which should be ok since that
check also require that all the involved binary operations has nuw).

Fixes #154116
2025-08-22 10:27:57 +02:00
Bjorn Pettersson
4ff7ac2330
[SeparateConstOffsetFromGEP] Add test case with trunc nuw/nsw showing miscompile
Pre commit a test case for issue #154116. When redistributing
trunc over add/sub/or we may need to drop poison generating flags
from the trunc.
2025-08-22 10:26:09 +02:00
Simon Pilgrim
8d7df8bba1
[X86] Allow AVX2 per-element shift intrinsics to be used in constexpr (#154780)
This handles constant folding for the AVX2 per-element shift intrinsics, which handle out of bounds shift amounts (logical result = 0, arithmetic result = signbit splat)

AVX512 intrinsics will follow in follow up patches

First stage of #154287
2025-08-22 09:24:24 +01:00
Pierre van Houtryve
4ab5efd48d
[AMDGPU][gfx1250] Add memory legalizer tests (NFC) (#154725) 2025-08-22 10:14:09 +02:00
Fangrui Song
f1aee598e7 ARM: Remove unneeded ARM::fixup_arm_thumb_bl special case
This is a weird special case added in 2015, simplifying an even older
condition. It is a no-op for ELF (isExternal is always false) and seems
unneeded for non-ELF.
2025-08-22 01:08:33 -07:00
LLVM GN Syncbot
2a59400003 [gn build] Port 2b8e80694263 2025-08-22 08:03:17 +00:00
Muhammad Omair Javaid
2b8e806942 Revert "[lldb-dap] Add module symbol table viewer to VS Code extension #140626 (#153836)"
This reverts commit 8b64cd8be29da9ea74db5a1a21f7cd6e75f9e9d8.

This breaks lldb-aarch64-* bots causing a crash in lldb-dap while
running test TestDAP_moduleSymbols.py

https://lab.llvm.org/buildbot/#/builders/59/builds/22959
https://lab.llvm.org/buildbot/#/builders/141/builds/10975
2025-08-22 13:02:52 +05:00
Zhaoxin Yang
149d9a38e1
[ELF][LoongArch] -r: Synthesize R_LARCH_ALIGN at input section start (#153935)
Similay to

94655dc8ae

The difference is that in LoongArch, the ALIGN is synthesized when the
alignment is >4, (instead of >=4), and the number of bytes inserted is
`sec->addralign - 4`.
2025-08-22 16:02:41 +08:00
Connector Switch
6560adb584
[flang] optimize atand/atan2d precision (#154544)
Part of https://github.com/llvm/llvm-project/issues/150452.
2025-08-22 15:55:46 +08:00
Matt Arsenault
2b46f31ee3
AMDGPU: Sign extend immediates for 32-bit subregister extracts (#154870)
extractSubregFromImm previously would sign extend the 16-bit subregister
extracts, but not the 32-bit. We try to consistently store immediates
as sign extended, since not doing it can result in misreported
isInlineImmediate checks.
2025-08-22 16:50:36 +09:00
Stanislav Mekhanoshin
e0945dfa30
[AMDGPU] Add test to show failure with SRC_*_HI registers. NFC. (#154828)
Since src_{private|shared}_{base|limit} registers are added and
are not artifical compiler happily uses it when it can. In HW
these registers do not exist and the encoding belongs to their
64-bit super-register or 32-bit low register. Same instructions
will produce relocation if run through asm.
2025-08-22 00:50:25 -07:00
Jay Foad
cf5243619a
[AMDGPU] Common up two local memory size calculations. NFCI. (#154784) 2025-08-22 08:44:11 +01:00
serge-sans-paille
50f7c6a5b9
Default to GLIBCXX_USE_CXX11_ABI=ON
Because many of our bots actually don't run a listdc++ compatible with
_GLIBCXX_USE_CXX11_ABI=0. See
https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_dual_abi.html for
details.

This is a follow-up to be179d069664ce03c485e49fa1f6e2ca3d6286fa related
to #154447.
2025-08-22 09:35:40 +02:00
paperchalice
945a186089
[DAGCombiner] Remove most UnsafeFPMath references (#146295)
This pull request removes all references to `UnsafeFPMath` in dag
combiner except FP_ROUND.
- Set fast math flags in some tests.
2025-08-22 15:27:25 +08:00
Fangrui Song
06ab660911 MCSymbol: Avoid isExported/setExported
The next change will move these methods from the base class.
2025-08-22 00:25:55 -07:00
Durgadoss R
36dc6146b8
[MLIR][NVVM] Update TMA tensor prefetch Op (#153464)
This patch updates the TMA Tensor prefetch Op
to add support for im2col_w/w128 and tile_gather4 modes.
This completes support for all modes available in Blackwell.
* lit tests are added for all possible combinations.
* The invalid tests are moved to a separate file with more coverage.

Signed-off-by: Durgadoss R <durgadossr@nvidia.com>
2025-08-22 12:51:29 +05:30
Djordje Todorovic
5050da7ba1
[RISCV] Add initial assembler/MC layer support for big-endian (#146534)
This patch adds basic assembler and MC layer infrastructure for
RISC-V big-endian targets (riscv32be/riscv64be):
      - Register big-endian targets in RISCVTargetMachine
      - Add big-endian data layout strings
      - Implement endianness-aware fixup application in assembler
        backend
      - Add byte swapping for data fixups on BE cores
      - Update MC layer components (AsmInfo, MCTargetDesc, Disassembler,
        AsmParser)
    
This provides the foundation for BE support but does not yet include:
      - Codegen patterns for BE
      - Load/store instruction handling
      - BE-specific subtarget features
2025-08-22 09:21:10 +02:00
Jason Molenda
a2f542b7a5
[lldb][debugserver] update --help to list all the options (#154853)
These are almost all for internal-developer-users only so "look at
debugserver.cpp" wasn't unreasonable, but we rarely add any new options
so a simple list of all recognized options isn't a burden to throw in
the help method.
2025-08-22 00:05:13 -07:00
Fangrui Song
04a3dd5a19 MCSymbol: Avoid isExported/setExported
The next change will move it to MCSymbol{COFF,MachO,Wasm} to make it
clear that other object file formats (e.g. ELF) do not use this field.
2025-08-22 00:00:29 -07:00
Fangrui Song
1def457228 MC: Avoid MCSymbol::isExported
This bit is only used by COFF/MachO. The upcoming change will move
isExported/setExported to MCSymbolCOFF/MCSymbolMachO.
2025-08-21 23:26:53 -07:00
Amit Kumar Pandey
d3d5751a39
[compiler-rt]: fix CodeQL format-string warnings via explicit casts (#153843)
This change addresses CodeQL format-string warnings across multiple
sanitizer libraries by adding explicit casts to ensure that printf-style
format specifiers match the actual argument types.

Key updates:
- Cast pointer arguments to (void*) when used with %p.
- Use appropriate integer types and specifiers (e.g., size_t -> %zu,
ssize_t -> %zd) to avoid mismatches.
- Fix format specifier mismatches across xray, memprof, lsan, hwasan,
dfsan.

These changes are no-ops at runtime but improve type safety, silence
static analysis warnings, and reduce the risk of UB in variadic calls.
2025-08-22 11:51:13 +05:30
Med Ismail Bennani
595148ab76
[lldb/crashlog] Avoid StopAtEntry when launch crashlog in interactive mode (#154651)
In 88f409194, we changed the way the crashlog scripted process was
launched since the previous approach required to parse the file twice,
by stopping at entry, setting the crashlog object in the middle of the
scripted process launch and resuming it.

Since then, we've introduced SBScriptObject which allows to pass any
arbitrary python object accross the SBAPI boundary to another scripted
affordance.

This patch make sure of that to include the parse crashlog object into
the scripted process launch info dictionary, which eliviates the need to
stop at entry.

Signed-off-by: Med Ismail Bennani <ismail@bennani.ma>

Signed-off-by: Med Ismail Bennani <ismail@bennani.ma>
2025-08-21 23:16:45 -07:00
Brad Smith
0fff460592
[Driver] DragonFly does not support C11 threads (#154886) 2025-08-22 02:02:52 -04:00
Rajat Bajpai
b08b219650
[MLIR][NVVM] Add "blocksareclusters" kernel attribute support (#154519)
This change adds "nvvm.blocksareclusters" kernel attribute support in NVVM Dialect/MLIR.
2025-08-22 11:32:21 +05:30
Mike Hommey
be179d0696
Be explicit about what libstdc++ C++11 ABI to use (#154447)
libstdc++ can be configured to default to a different C++11 ABI, and
when the system that is used to build clang has a different default than
the system used to build a clang plugin, that leads to uses of different
ABIs, leading to breakage (missing symbols) when using clang APIs that
use types like std::string.

We arbitrarily choose to default to the old ABI, but the user can opt-in
to the new ABI. The important part is that whichever is picked is
reflected in llvm-config's output.
2025-08-22 05:55:42 +00:00
Craig Topper
dee25a8a8e
[TableGen] Validate the shift amount for !srl, !shl, and !sra operators. (#132492)
The C operator has undefined behavior for out of bounds shifts so we
should check this.
2025-08-21 22:41:36 -07:00
Frederik Harwath
d6fae7f921
Reapply "[Clang] Take libstdc++ into account during GCC detection" #145056 (#154487)
The Generic_GCC::GCCInstallationDetector class picks the GCC installation directory with the largest version number. Since the location of the libstdc++ include directories is tied to the GCC version, this can break C++ compilation if the libstdc++ headers for this particular GCC version are not available. Linux distributions tend to package the libstdc++ headers separately from GCC. This frequently leads to situations in which a newer version of GCC gets installed as a dependency of another package without installing the corresponding libstdc++ package. Clang then fails to compile C++ code because it cannot find the libstdc++ headers. Since libstdc++ headers are in fact installed on the system, the GCC installation continues to work, the user may not be aware of the details of the GCC detection, and the compiler does not recognize the situation and emit a warning, this behavior can be hard to understand - as witnessed by many related bug reports over the years.

The goal of this work is to change the GCC detection to prefer GCC installations that contain libstdc++ include directories over those which do not. This should happen regardless of the input language since picking different GCC installations for a build that mixes C and C++ might lead to incompatibilities.
Any change to the GCC installation detection will probably have a negative impact on some users. For instance, for a C user who relies on using the GCC installation with the largest version number, it might become necessary to use the --gcc-install-dir option to ensure that this GCC version is selected.
This seems like an acceptable trade-off given that the situation for users who do not have any special demands on the particular GCC installation directory would be improved significantly.
 
This patch does not yet change the automatic GCC installation directory choice. Instead, it does introduce a warning that informs the user about the future change if the chosen GCC installation directory differs from the one that would be chosen if the libstdc++ headers are taken into account.

See also this related Discourse discussion: https://discourse.llvm.org/t/rfc-take-libstdc-into-account-during-gcc-detection/86992.

This patch reapplies #145056. The test in the original PR did not specify a target in the clang RUN line and used a wrong way of piping to FileCheck.
2025-08-22 07:39:11 +02:00
Craig Topper
630712f4c1
[RISCV] Add a helper class to reduce PseudoAtomicLoadNand* pattern duplication. NFC (#154838) 2025-08-21 22:35:28 -07:00
Matt Arsenault
b1b5102624
AMDGPU: Start considering new atomicrmw metadata on integer operations (#122138)
Start considering !amdgpu.no.remote.memory.access and
!amdgpu.no.fine.grained.host.memory metadata when deciding to expand
integer atomic operations. This does not yet attempt to accurately
handle fadd/fmin/fmax, which are trickier and require migrating the
old "amdgpu-unsafe-fp-atomics" attribute.
2025-08-22 05:29:36 +00:00
Lang Hames
c1625fad02
[orc-rt] Rename unique_function to move_only_function. (#154888)
This will allow the ORC runtime and its clients to easily adopt the
c++-23 std::move_only_function type.
2025-08-22 15:26:10 +10:00
Craig Topper
c346f4079a
[RISCV] Use llvm_anyint_ty instead of llvm_any_ty for scalar intrinsics. NFC (#154816) 2025-08-21 22:18:39 -07:00
Matt Arsenault
fc5fcc0c95
AMDGPU: Start using AV_MOV_B64_IMM_PSEUDO (#154500) 2025-08-22 13:59:36 +09:00
Matt Arsenault
01f785cac4
AMDGPU: Expand remaining system atomic operations (#122137)
System scope atomics need to use cmpxchg loops if we know
nothing about the allocation the address is from.
aea5980e26e6a87dab9f8acb10eb3a59dd143cb1 started this, this
expands the set to cover the remaining integer operations.

Don't expand xchg and add, those theoretically should work over PCIe.
This is a pre-commit which will introduce performance regressions.
Subsequent changes will add handling of new atomicrmw metadata, which
will avoid the expansion.

Note this still isn't conservative enough; we do need to expand
some device scope atomics if the memory is in fine-grained remote
memory.
2025-08-22 13:55:04 +09:00
Sergei Barannikov
6a7ade03d1
[TableGen][DecoderEmitter] Remove redundant variable (NFC) (#154880)
`NumFiltered` is the number of elements in all vectors in a map.
It is ever compared to 1, which is equivalent to checking if the map
contains exactly one vector with exactly one element.
2025-08-22 04:42:06 +00:00
Craig Topper
586a7131d3
[RISCV][LoongArch] Prefix tablegen class names for intrinsics with 'RISCV'. NFC (#154821)
All targets are included by Intrinsics.td so we should name things
carefully to avoid interfering with other targets.

Copy one class that LoongArch was also using.
2025-08-21 21:40:35 -07:00
Jordan Rupprecht
49d4712129
[bazel] Port #154774: unroll vector.from_elements (#154882) 2025-08-22 04:33:50 +00:00
Lang Hames
6df9a13e40
[orc-rt] Use LLVM-style header naming scheme. (#154881)
This is more consistent with the rest of the LLVM project, and the
resulting names are closer to the types defined in each of the headers.
2025-08-22 14:28:02 +10:00
dpalermo
d26ea02060
Revert "Fix Debug Build Using GCC 15" (#154877)
Reverts llvm/llvm-project#152223
2025-08-21 21:54:58 -05:00
Yang Bai
f1f194bf10
[mlir][vector] fix: unroll vector.from_elements in gpu pipelines (#154774)
### Problem

PR #142944 introduced a new canonicalization pattern which caused
failures in the following GPU-related integration tests:

-
mlir/test/Integration/GPU/CUDA/TensorCore/sm80/transform-mma-sync-matmul-f16-f16-accum.mlir
-
mlir/test/Integration/GPU/CUDA/TensorCore/sm80/transform-mma-sync-matmul-f32.mlir

The issue occurs because the new canonicalization pattern can generate
multi-dimensional `vector.from_elements` operations (rank > 1), but the
GPU lowering pipelines were not equipped to handle these during the
conversion to LLVM.

### Fix

This PR adds `vector::populateVectorFromElementsLoweringPatterns` to the
GPU lowering passes that are integrated in `gpu-lower-to-nvvm-pipeline`:

- `GpuToLLVMConversionPass`: the general GPU-to-LLVM conversion pass.
- `LowerGpuOpsToNVVMOpsPass`: the NVVM-specific lowering pass.

Co-authored-by: Yang Bai <yangb@nvidia.com>
2025-08-21 21:46:06 -05:00
Sergei Barannikov
418fb50301
[TableGen][DecoderEmitter] Calculate encoding bits once (#154026)
Parse the `Inst` and `SoftField` fields once and store them in
`InstructionEncoding` so that we don't parse them every time
`getMandatoryEncodingBits()` is called.
2025-08-22 05:19:35 +03:00
Lang Hames
273b6f2911
[orc-rt] Add orc_rt::unique_function. (#154874)
A bare-bones version of LLVM's unique_function: this behaves like a
std::unique_function, except that it supports move only callable types.
2025-08-22 12:19:15 +10:00
Muhammad Bassiouni
4d323206ed
[libc][math] Refactor cospif16 implementation to header-only in src/__support/math folder. (#154222)
Part of #147386

in preparation for: https://discourse.llvm.org/t/rfc-make-clang-builtin-math-functions-constexpr-with-llvm-libc-to-support-c-23-constexpr-math-functions/86450
2025-08-22 05:04:13 +03:00
Lang Hames
3ce25abd4a
[orc-rt] Add error.h: structured error support. (#154869)
Adds support for the Error class, Expected class template, and related
APIs that will be used for error propagation and handling in the new ORC
runtime.

The implementations of these types are cut-down versions of similar APIs
in llvm/Support/Error.h. Most advice on llvm::Error and llvm::Expected
(e.g. from the LLVM Programmer's manual) applies equally to
orc_rt::Error and orc_rt::Expected.

Ported from the old ORC runtime at compiler-rt/lib/orc.
2025-08-22 11:53:47 +10:00
Muhammad Bassiouni
783859b2a0
[libc][math] Refactor cospif implementation to header-only in src/__support/math folder. (#154215)
Part of #147386

in preparation for: https://discourse.llvm.org/t/rfc-make-clang-builtin-math-functions-constexpr-with-llvm-libc-to-support-c-23-constexpr-math-functions/86450
2025-08-22 04:53:18 +03:00
Aiden Grossman
9d2a66fb32 [Clang] Slightly clean up __cpuidex_conflict.c
This was intended to be fixed in #154217, but given that didn't land, it
still needs to be done. I think it still makes sense to have this change
in.
2025-08-22 01:37:17 +00:00
Anthony Latsis
0bc02096f6
[clang] Upstream clang::CodeGen::getConstantSignedPointer (#154453)
This function was introduced to Swift's fork in

https://github.com/swiftlang/llvm-project/commit/a9dd959e60c32#diff-db27b2738ad84e3f1093f9174710710478f853804d995a6de2816d1caaad30d1.

The Swift compiler cannot use `CodeGenModule::getConstantSignedPointer`,
to which it forwards, because that is a private interface.
2025-08-21 17:55:57 -07:00
Craig Topper
6167b1e6e9
[TableGen] Remove unnecessary use of utostr when writing to raw_ostream. NFC (#154800)
raw_ostream is capable of printing unsigned or uint64_t directly.
2025-08-21 17:44:53 -07:00
Sergei Barannikov
b3f04bf44c [M68k] Rename a generated file to be consistent with other targets (NFC) 2025-08-22 03:38:30 +03:00
Rahul Joshi
4eeeb8a01e
[NFC][MC][Decoder] Fix off-by-one indentation in generated code (#154855) 2025-08-21 17:20:05 -07:00
Luke Lau
c97c6869b6
[VPlan] Allow folding not (cmp eq) -> icmp ne with other select users (#154497)
Currently we only allow folding not (cmp eq) -> icmp ne if the not is
the only user of the compare.
However a common scenario is that some select might also use the
compare. We can still fold the not if we also swizzle the arms of the
selects.

This helps avoid regressions in #150368
2025-08-22 07:59:14 +08:00
Wenju He
e6d095e89c
[libclc] Only create a target per each compile command for cmake MSVC generator (#154479)
libclc sequential build issue addressed in commit 0c21d6b4c8ad is
specific to cmake MSVC generator. Therefore, this PR avoids creating a
large number of targets when a non-MSVC generator is used, such as the
Ninja generator, which is used in pre-merge CI on Windows in
llvm-project repo. We plan to migrate from MSVC generator to Ninja
generator in our downstream CI to fix flaky cmake bug `Cannot restore
timestamp`, which might be related to the large number of targets.
2025-08-22 07:45:42 +08:00
Med Ismail Bennani
05b1ec3724
[lldb/API] Add setters to SBStructuredData (#154445)
This patch adds setters to the SBStruturedData class to be able to
initialize said object from the client side directly.

Signed-off-by: Med Ismail Bennani <ismail@bennani.ma>
2025-08-21 16:40:01 -07:00
Peter Collingbourne
ff85dbdf6b
ThinLTOBitcodeWriter: Emit __cfi_check to full LTO part of bitcode file.
The CrossDSOCFI pass runs on the full LTO module and fills in the
body of __cfi_check. This function must have the correct attributes in
order to be compatible with the rest of the program. For example, when
building with -mbranch-protection=standard, the function must have the
branch-target-enforcement attribute, which is normally added by Clang.
When __cfi_check is missing, CrossDSOCFI will give it the default set
of attributes, which are likely incorrect. Therefore, emit __cfi_check
to the full LTO part, where CrossDSOCFI will see it.

Reviewers: efriedma-quic, vitalybuka, fmayer

Reviewed By: efriedma-quic

Pull Request: https://github.com/llvm/llvm-project/pull/154833
2025-08-21 16:31:32 -07:00
David Majnemer
f961b61f88 [APFloat] Properly implement DoubleAPFloat::compareAbsoluteValue
The prior implementation would treat X+Y and X-Y as having equal
magnitude.  Rework the implementation to be more resilient.
2025-08-21 15:42:07 -07:00
Sergei Barannikov
c74afaac6c
[TableGen][DecoderEmitter] Use KnownBits for filters/encodings (NFCI) (#154691)
`KnownBits` is faster and smaller than `std::vector<BitValue>`.
It is also more convenient to use.
2025-08-22 01:37:47 +03:00
Alex MacLean
a3ed96b899
[NVPTX] Legalize aext-load to zext-load to expose more DAG combines (#154251) 2025-08-21 15:33:23 -07:00
Patrick Simmons
304373fb6d
Fix Debug Build Using GCC 15 (#152223)
Flang currently doesn't build in debug mode on GCC 15 due to missing
dynamic libraries in some CMakeLists.txt files, and OpenMP doesn't link
in debug mode due to the atomic library pulling in libstdc++ despite an
incomplete attempt in the CMakeLists.txt to disable glibcxx assertions.
This PR fixes these issues and allows Flang and the OpenMP runtime to
build and link on GCC 15 in debug mode.

---------

Co-authored-by: ronlieb <ron.lieberman@amd.com>
2025-08-21 18:28:01 -04:00
John Harrison
36d07ad83b
Reapply "[lldb-dap] Re-land refactor of DebugCommunication. (#147787)" (#154832)
This reverts commit 0f33b90b6117bcfa6ca3779c641c1ee8d03590fd and
includes a fix for the added test that was submitted between my last
update and pull.
2025-08-21 15:26:52 -07:00
Sergei Barannikov
33f6b10c17
[TableGen][DecoderEmitter] Resolve a FIXME in emitDecoder (#154649)
As the FIXME says, we might generate the wrong code to decode an
instruction if it had an operand with no encoding bits. An example is
M68k's `MOV16ds` that is defined as follows:

```
dag OutOperandList = (outs MxDRD16:$dst);
dag InOperandList = (ins SRC:$src);
list<Register> Uses = [SR];
string AsmString = "move.w\t$src, $dst"
dag Inst = (descend { 0, 1, 0, 0, 0, 0, 0, 0, 1, 1 },
            (descend { 0, 0, 0 }, (operand "$dst", 3)));
```

The `$src` operand is not encoded, but what we see in the decoder is:
```C++
    tmp = fieldFromInstruction(insn, 0, 3);
    if (!Check(S, DecodeDR16RegisterClass(MI, tmp, Address, Decoder)))
    { return MCDisassembler::Fail; }
    if (!Check(S, DecodeSRCRegisterClass(MI, insn, Address, Decoder)))
    { return MCDisassembler::Fail; }
    return S;
```

This calls DecodeSRCRegisterClass passing it `insn` instead of the value
of a field that doesn't exist. DecodeSRCRegisterClass has an
unconditional llvm_unreachable inside it.

New decoder looks like:
```C++
    tmp = fieldFromInstruction(insn, 0, 3);
    if (!Check(S, DecodeDR16RegisterClass(MI, tmp, Address, Decoder)))
    { return MCDisassembler::Fail; }
    return S;
```

We're still not disassembling this instruction right, but at least we no
longer have to provide a weird operand decoder method that accepts
instruction bits instead of operand bits.

See #154477 for the origins of the FIXME.
2025-08-21 22:22:16 +00:00
Dave Lee
d4b9acad58
[lldb] Fix TestSettings.py (#154849)
Fixes a few test failures on windows. See
https://github.com/llvm/llvm-project/pull/153233
2025-08-21 15:19:44 -07:00
Shubham Sandeep Rastogi
7f0e70fd2d [CMake] Update CMAKE_OSX_DEPLOYMENT_TARGET to 10.13.
The greendragon standalone bot is complaining about the deployment
target needing to be 10.13 or above. This change makes it 10.13
2025-08-21 15:09:31 -07:00
Rahul Joshi
22f8693248
[NFC][MC][Decoder] Extract fixed pieces of decoder code into new header file (#154802)
Extract fixed functions generated by decoder emitter into a new
MCDecoder.h header.
2025-08-21 15:06:43 -07:00
Kazu Hirata
628280b597
[memprof] Tidy up #includes (NFC) (#154684)
We've reorganized some code within memprof, but #indludes haven't
quite followed the code that moved.
2025-08-21 15:03:40 -07:00
Kazu Hirata
67e95c6f60
[llvm] Proofread DebuggingCoroutines.rst (#154681) 2025-08-21 15:03:32 -07:00
Kazu Hirata
4e98641451
[ADT] Use SmallPtrSet or SmallSet flexibly (NFC) (#154680)
I'm trying to remove the redirection in SmallSet.h:

template <typename PointeeType, unsigned N>
class SmallSet<PointeeType*, N> : public SmallPtrSet<PointeeType*, N>
{};

to make it clear that we are using SmallPtrSet.  There are only
handful places that rely on this redirection.

Now, this unit test is unique in that supply multiple key types via
TYPED_TESTS.

This patch adds UniversalSmallSet to work around the problem.
2025-08-21 15:03:24 -07:00
Kazu Hirata
ec07d8e941
[clang-tidy] Use SmallPtrSet directly instead of SmallSet (NFC) (#154679)
I'm trying to remove the redirection in SmallSet.h:

template <typename PointeeType, unsigned N>
class SmallSet<PointeeType*, N> : public SmallPtrSet<PointeeType*, N>
{};

to make it clear that we are using SmallPtrSet.  There are only
handful places that rely on this redirection.

This patch replaces SmallSet to SmallPtrSet where the element type is
a pointer.
2025-08-21 15:03:16 -07:00
Kazu Hirata
f5f6613af6
[Scalar] Use SmallSetVector instead of SmallVector (NFC) (#154678)
insertParsePoints collects live variables and then deduplicate them
while retaining the original insertion order, which is exactly what
SetVector is designed for.  This patch replaces SmallVector with
SetSmallVector while deleting unique_unsorted.

While we are at it, this patch reduces the number of inline elements
to a reasonable level for linear search.
2025-08-21 15:03:08 -07:00
Thurston Dang
e45210afe2
[msan] Handle AVX512 VCVTPS2PH (#154460)
This extends handleAVX512VectorConvertFPToInt() from
556c8467d15a131552e3c84478d768bafd95d4e6
(https://github.com/llvm/llvm-project/pull/147377) to handle AVX512
VCVTPS2PH.
2025-08-21 15:03:01 -07:00
Valentin Clement (バレンタイン クレメン)
1d05d693a1
[flang][cuda] Fix offset with multiple assumed size shared array (#154844)
When multiple assumed size variable are used in a kernel with dynamic
shared memory, each variable use the 0 offset. Update the pass to
account for that.

```
attributes(global) subroutine testany( a )
    real(4), shared :: smasks(*)
    real(8), shared :: dmasks(*)
end subroutine
```
2025-08-21 21:51:43 +00:00
Justin Riddell
fa67855c99
[CIR] Handle FunctionToPointerDecay casts (#153657) (#154060)
Add upstream support for handling implicit FunctionToPointerDecay casts
2025-08-21 14:40:14 -07:00
Sergei Barannikov
2421929ca6
[TableGen][DecoderEmitter] Infer encoding's HasCompleteDecoder earlier (NFCI) (#154644)
If an encoding has a custom decoder, the decoder is assumed to be
"complete" (always succeed) if hasCompleteDecoder field is true. We
determine this when constructing InstructionEncoding.

If the decoder for an encoding is *generated*, it always succeeds if
none of the operand decoders can fail. The latter is determined based on
the value of operands' DecoderMethod/hasCompleteDecoder. This happens
late, at table construction time, making the code harder to follow.

This change moves this logic to the InstructionEncoding constructor.
2025-08-21 21:35:30 +00:00
Rahul Joshi
d38a5afa5a
[NFC][MC][ARM] Fix formatting for ITStatus and VPTStatus (#154815) 2025-08-21 14:26:18 -07:00
Craig Topper
04a271adf8
[RISCV] Reorder atomic pseudo instructions and isel patterns. NFC (#154835)
Instead of interleaving the pseudo definitions and their patterns,
define all the pseudos together and all the patterns together.

Add IsRV32 predicate to the patterns.
2025-08-21 14:22:02 -07:00
Joseph Huber
c704dabe88
[Clang] Fix incorrect return type for __builtin_shufflevector (#154817)
Summary:
The `__builtin_shufflevector` call would return a GCC vector in all
cases where the vector type was increased. Change this to preserve
whether or not this was an extended vector.

Fixes: https://github.com/llvm/llvm-project/issues/107981
2025-08-21 16:13:52 -05:00
Michael Buch
8fa55a023b
[clang][DebugInfo][test] Move debug-info tests from CodeGenObjC to DebugInfo directory (#154781)
This patch works towards consolidating all Clang debug-info into the
`clang/test/DebugInfo` directory
(https://discourse.llvm.org/t/clang-test-location-of-clang-debug-info-tests/87958).

Here we move only the `clang/test/CodeGenObjC` tests.

The list of files i came up with is:
1. searched for anything with `*debug-info*` in the filename
2. searched for occurrences of `debug-info-kind` in the tests
2025-08-21 22:09:34 +01:00
Dan Liew
09612007f1
[NFC][Diagnostics] Reformat DiagnosticIDs.h and AllDiagnostics.h (#154628)
When trying to add a new diagnostic category (e.g. #154618) I discovered
`clang-format` really wanted to reformat these files.

My initial attempt was just to suppress the reformatting with `//
clang-format (on|off)` directives but reviewers preferred just
reformatting the files so these two files have been completely
reformatted.

`clang-format` has been disabled for the enum that declares the
`DIAG_START_*` constants because its much less readable after
formatting.
2025-08-21 14:06:49 -07:00
Florian Hahn
300d2c6d20
[VPlan] Move SCEV expansion to VPlan transform. (NFCI).
Move the logic to expand SCEVs directly to a late VPlan transform that
expands SCEVs in the entry block. This turns VPExpandSCEVRecipe into an
abstract recipe without execute, which clarifies how the recipe is
handled, i.e. it is not executed like regular recipes.

It also helps to simplify construction, as now scalar evolution isn't
required to be passed to the recipe.
2025-08-21 22:03:26 +01:00
ykhatav
38f0b9e6d9
Fix scope of typedefs present inside a template class (#146729)
When a typedef is declared within a templated class, clang incorrectly
assigns the typedef to the compilation unit (CU) scope rather than the
intended scope of the templated class. This issue arises because, during
the creation of the typedef, the context lookup in the RegionMap fails
to locate the templated class, despite its prior creation.
The problem stems from the way the context is stored in the RegionMap.
When handling templated types, the current implementation stores the
class specialization rather than the templated declaration itself. This
leads to a mismatch when attempting to retrieve the context for the
typedef.
To address this issue, the solution involves modifying the
CreatedLimitedType() function. Specifically, when a struct or class is a
templated type, we should store the actual templated declaration in the
RegionMap instead of the class specialization. This ensures that
subsequent lookups for context, such as those needed for typedef
declarations, correctly identify the templated class scope.
Fixes https://github.com/llvm/llvm-project/issues/91451
2025-08-21 16:58:25 -04:00
Alex MacLean
9b24ccca73
[NVPTX] Allow more argument integer types, such as i256 and i96 (#154824)
The refactoring of ComputePTXValueVTs in #154476 caused the complier to
no longer crash when lowering i256 and i96. This has caused a few tests
to unexpectedly pass.

Update these tests and tweak how we emit parameter declarations to
correctly lower these types.
2025-08-21 13:54:38 -07:00
Dave Lee
933d8723b0
[llvm][utils] Improve the StringRef summary formatter (#151594)
Improve the `StringRef` summary formatter in the following ways:
* inherit adherence to the `target.max-string-summary-length` setting
* support non-printable bytes (such as null bytes, and any other binary data)

With the previous implementation, some non-printable bytes would raise a
Python exception.
2025-08-21 13:42:49 -07:00
Dave Lee
545cda649e
[lldb] Add flag to "settings show" to include default values (#153233)
Adds a `--defaults`/`-d` flag to `settings show`. This mode will _optionally_ show a
setting's default value. In other words, this does not always print a default value for
every setting.

A default value is not shown when the current value _is_ the default.

Note: some setting types do not print empty or invalid values. For these setting types,
if the default value is empty or invalid, the same elision logic is applied to printing
the default value.
2025-08-21 13:41:38 -07:00
Florian Hahn
ba5d487ac4
[LV] Add test with interleave groups separated by offset.
Adds extra test coverage for
https://github.com/llvm/llvm-project/pull/91196.
2025-08-21 21:40:47 +01:00
Alex MacLean
4a9d2187ee
[SeparateConstOffsetFromGEP] propagate const offset through GEP chains (#143470)
When separating the constant offset from a GEP, if the pointer operand
is a constant ptradd (likely generated when we performed this transform
on that GEP), we accumulate the offset into the current offset. This
ensures that when there is a chain of GEPs the constant offset reaches
the final memory instruction where it can likely be folded into the
addressing.
2025-08-21 13:37:24 -07:00
Scott Linder
76b8e19203
[LangRef] Rework DIExpression docs (#153072)
Factor out most of the DIExpression docs from LangRef.rst into
SourceLevelDebugging.rst

What remains in LangRef is just enough context to make sense of how
DIExpression-as-metadata fits into the IR, including some examples of
the DIExpression syntax.

The rest now lives in the SourceLevelDebugging document, which gives
more context to make sense of DIExpression-as-semantic-entity.

Use sections to clearly separate DWARF opcodes from LLVM internal-only
opcodes, where before the distinction was only explicit in the source
code.

Also make some other changes like fixing typos, using :ref: rather than
unchecked links, and rewording DW_OP_LLVM_entry_value.
2025-08-21 16:32:53 -04:00
Dave Lee
a447fc63f9
[lldb] Improve error message in ResolveSDKPathFromDebugInfo (NFC) (#154607)
While debugging, I saw a log line of:

> Failed to resolve SDK path: Error while searching for SDK (XcodeSDK ''): Unrecognized SDK type:

Looking into how this might happen, it seems `ResolveSDKPathFromDebugInfo` appears to
(implicitly) assume there's at least one compile unit. This change adds a precondition
to return a meaningful error when there are no compile units.

Original: https://github.com/llvm/llvm-project/pull/146062
2025-08-21 13:23:38 -07:00
James Newling
a64e6f4928
[MLIR][Vector] Test to accompany bug fix (#154434)
Bug introduced in 
https://github.com/llvm/llvm-project/pull/93664

The bug was fixed in
https://github.com/llvm/llvm-project/pull/152957

But there was no test. This PR adds a test that hits the assertion
failure if the fix is reverted (if I change dyn_cast to cast).
2025-08-21 13:00:41 -07:00
Ramkumar Ramachandra
de7bac6426
[VPlan/PatternMatch] Strip outdated hdr comment (NFC) (#154794) 2025-08-21 20:43:03 +01:00
Carlos Galvez
344793e513
[clang-tidy][doc] Improve option docs for readability-identifier-naming (#154806)
Currently it's hard to find the "general" options, since they are listed
in the middle of the "specific" options. Split them into two categories
so they are easier to find.

This can help in adding a potential new general option in a follow-up
patch.

Co-authored-by: Carlos Gálvez <carlos.galvez@zenseact.com>
2025-08-21 21:41:24 +02:00
Peter Collingbourne
b3baa4d063 gn build: Port 4c9b7ff04cb4 2025-08-21 12:15:37 -07:00
Peter Collingbourne
779bb04a9a [gn build] Port fea7e6934a25 2025-08-21 12:15:37 -07:00
Peter Collingbourne
9b5282723b [gn build] Port eb764040bccc 2025-08-21 12:15:37 -07:00
Peter Collingbourne
4e7779c099 [gn build] Port deab049b5cc8 2025-08-21 12:15:36 -07:00
Peter Collingbourne
8d69c83808 [gn build] Port 8b64cd8be29d 2025-08-21 12:15:36 -07:00
Peter Collingbourne
7d1f15c985 [gn build] Port 87a1d42bed3d 2025-08-21 12:15:36 -07:00
Peter Collingbourne
f66d7b50ff [gn build] Port 15babbaf5d40 2025-08-21 12:15:36 -07:00
Shubham Sandeep Rastogi
0f33b90b61 Revert "[lldb-dap] Re-land refactor of DebugCommunication. (#147787)"
This reverts commit 13eca5248c7bf625af9c7af898d48e8c0a441496.

This change broke greendragon lldb test:

lldb-api.tools/lldb-dap/moduleSymbols.TestDAP_moduleSymbols.py
2025-08-21 12:12:46 -07:00
Craig Topper
424521f599
[RISCV] Correct the OperandType for simm8_unsigned and simm10_unsigned. (#154667) 2025-08-21 12:01:07 -07:00
William Huynh
1b9e9e29e2
[libc] Add boot code for AArch64 (#154789)
This is required in hermetic testing downstream. It is not complete, and
will not work on hardware, however it runs on QEMU, and can report a
pass/fail on our tests.
2025-08-21 18:47:34 +00:00
Tom Honermann
c80b7822e3
[NFC][SYCL] Test use of sycl_kernel_entry_point with null declarations and statements. (#154583)
The `sycl_kernel_entry_point` attribute only appertains to functions.
This change adds missing tests to validate that an appropriate
diagnostic is issued for likely unintentional application of the
attribute to a null declaration or a null statement; perhaps due to an
unintended semicolon.
2025-08-21 14:47:07 -04:00
Thurston Dang
de64f85f5d
[hwasan] Port "[Asan] Skip pre-split coroutine and noop coroutine frame (#99415)" (#154803)
Originally suggested by rnk@

(this is the simplified function-level skip version, to unblock builds
ASAP)
2025-08-21 11:20:35 -07:00
Sebastian Pop
e42ef8083c
[delinearize] use update_analyze_test_checks.py in delinearization testcases (#153831)
In this patch:
1. Adapt the output of printDelinearization() to match what the script
   expects to see, "Printing analysis 'Delinearization' for function".
2. Register the "Delinearization" pass in the update script.
3. Automatically remove the existing CHECK statements.
4. Update the tests with a run of:
```
$ ~/llvm-project/llvm/utils/update_analyze_test_checks.py
        --opt=~/llvm-project/build/bin/opt
        ~/llvm-project/llvm/test/Analysis/Delinearization/*.ll
```
5. Drop llvm/test/Analysis/Delinearization/undef.ll because the test
   does not pass the github-actions "undef deprecator."
6. Only run delinearization pretty-print pass on the most internal loop.
7. Only run delinearization pretty-print pass on load and store
   instructions.
2025-08-21 13:02:56 -05:00
Timm Baeder
8b091961b1
[clang][bytecode] Implement Pointer::getType() for function pointers (#154788)
Fixes #152920
2025-08-21 20:01:22 +02:00
Florian Hahn
e41aaf5a64
[VPlan] Use VPIRMetadata for VPInterleaveRecipe. (#153084)
Use VPIRMetadata for VPInterleaveRecipe to preserve noalias metadata
added by versioning.

This still uses InterleaveGroup's logic to preserve existing metadata
from IR. This can be migrated separately.

Fixes https://github.com/llvm/llvm-project/issues/153006.

PR: https://github.com/llvm/llvm-project/pull/153084
2025-08-21 18:58:10 +01:00
Florian Hahn
21cca5ea9d
[VPlan] Rely on VPlan opts to simplify multiply by 1 (NFCI). 2025-08-21 18:43:47 +01:00
David Green
11994e8da7
[AArch64][GlobalISel] Mark G_BR as always legal. NFC (#153545)
As far as I understand this will not affect anything, just lower the
exposure to the legacy legalizer rules.
2025-08-21 18:42:44 +01:00
Craig Topper
c91f7dc7cd
[TableGen] Remove dummy UINT64_C(0) from end of InstBits table. NFC (#154778)
I suspect this originally existed to avoid a trailing comma from the
previous entry. C++ allows trailing commas in arrays so this isn't
necessary.
2025-08-21 10:42:37 -07:00
David Green
1a09581aa1
[AArch64][GlobalISel] Be more precise in RegBankSelect for s/uitofp (#154489)
We can generate fpr->fpr instructions for G_SITOFP and G_UITOFP. It was
previously marking the instructions as FPR but then generating GPR
instructions and introducing a copy.
2025-08-21 17:41:01 +00:00
Finn Plummer
87a1d42bed
[DirectX] Add support for remove-section of DXContainer for llvm-objcopy (#153246)
This pr implements the `remove-section` option for a `DXContainer`
object in `llvm-objcopy`.

It implements a base `removeParts` to the minimal `object`
representation of a `DXContainerObject`.

This is the second step to implement
https://github.com/llvm/llvm-project/issues/150275 as a compiler actions
that invokes llvm-objcopy for functionality.
2025-08-21 10:30:54 -07:00
Alex MacLean
a9de1ab44d
[NVPTX] Disable v2f32 registers when no operations supported, or via cl::opt (#154476)
The addition of v2f32 as a legal type, supported by the B64 register
class, has caused performance regressions, broken inline assembly, and
resulted in a couple (now fixed) mis-compilations. In order to mitigate
these issues, only mark this as a legal type when there exist operations
that support it, since for targets where this is not the case it serves
no purpose. To enable further debugging, add an option to disable v2f32.

In order to allow for a target-dependent set of legal types,
ComputePTXValueVTs has been fully re-written to take advantage of
TargetLowering call-lowering APIs.
2025-08-21 10:30:36 -07:00
Aiden Grossman
0319a7970d
[CI] Disable PIE on Linux Premerge Builds (#154584)
We do not gain any additional security from having PIE on the test
binaries, and this does have an impact on test times. It is about 10%
from my measurements. Not as much as previous reports
(https://reviews.llvm.org/D140880), but still significant. This is a
similar gain to finish enabling the lit internal shell, which will take
significantly more effort. I also do not think this is a meaningful
enough difference from the "default" configuration to keep it the
default, especially given the option is mostly set by distros.
2025-08-21 10:21:02 -07:00
John Harrison
13eca5248c
[lldb-dap] Re-land refactor of DebugCommunication. (#147787)
Originally commited in 362b9d78b4ee9107da2b5e90b3764b0f0fa610fe and then
reverted in cb63b75e32a415c9bfc298ed7fdcd67e8d9de54c.

This re-lands a subset of the changes to
dap_server.py/DebugCommunication and addresses the python3.10
compatibility issue.

This includes less type annotations since those were the reason for the
failures on that specific version of python.

I've done additional testing on python3.8, python3.10 and python3.13 to
further validate these changes.
2025-08-21 10:20:01 -07:00
Anchu Rajendran S
bce9b6d177
[Flang][Flang-Driver]Fix to add atomic control options in non-fc1 mode (#154638) 2025-08-21 10:15:33 -07:00
Andy Kaylor
c5466c64d4
[CIR] Add CIR vtable attribute (#154415)
This adds the #cir.vtable attribute definition and verification.
Generation of the vtable will be implemented in a later change.
2025-08-21 09:52:14 -07:00
7mile
761125f267
[CIR][Dialect] Add SourceLangAttr (#152511)
This patch upstreams `SourceLangAttr` and its CodeGen logic in the CGM,
which encodes the source language in CIR.
2025-08-21 09:51:37 -07:00
Shafik Yaghmour
436f391d1d
[Clang][Codegen][NFC] Apply rule of three to some classes (#154671)
Static analysis flagged these classes as having implemented the
destructor but not applying rule of three. This could lead to accidental
misuse and so it makes sense to apply it.
2025-08-21 09:36:25 -07:00
Florian Hahn
b5fc4fd009
[LAA] Add test requiring runtime checks with -max-dependences flag.
Adds extra test coverage for
https://github.com/llvm/llvm-project/pull/91196.
2025-08-21 17:31:53 +01:00
Jordan Rupprecht
9576a100ae
[bazel] Port #152474: RemarkEngine (#154792) 2025-08-21 16:29:50 +00:00
Leandro Lacerda
eed5f06ae8
[Offload][Conformance] Add randomized tests for single-precision bivariate math functions (#154663)
This patch adds a new set of randomized conformance tests for
single-precision bivariate math functions.

The functions included in this set were selected based on the following
criteria:
- An implementation exists in `libc/src/math/generic` (i.e., it is not
just a wrapper around a compiler built-in).
- The corresponding LLVM CPU libm implementation is correctly rounded.
- The function is listed in Table 65 of the OpenCL C Specification
v3.0.19.
2025-08-21 11:27:25 -05:00
Tim Gymnich
e20fa4f412
[mlir][AMDGPU] Add PermlaneSwapOp (#154345)
- Add PermlaneSwapOp that lowers to `rocdl.permlane16.swap` and
`rocdl.permlane32.swap`

---------

Co-authored-by: Jakub Kuderski <kubakuderski@gmail.com>
2025-08-21 18:21:43 +02:00
Andres-Salamanca
fc62990657
[CIR] Upstream GotoSolver pass (#154596)
This PR upstreams the GotoSolver pass.  
It works by walking the function and matching each label to a goto. If a
label is not matched to a goto, it is removed and not lowered.
2025-08-21 11:02:29 -05:00
Timm Baeder
3923adfa3f
[clang][bytecode] Guard strcmp against differing element types (#154777)
This can happen when casts are involved.

Fixes #154006
2025-08-21 18:02:08 +02:00
Dave Lee
dacabc1fee
[lldb] Tweak check for CommandLineTools in ParseXcodeSDK (#154574)
Follow up to https://github.com/llvm/llvm-project/pull/128712
2025-08-21 08:56:17 -07:00
Dave Lee
86c9a7b0c1
[lldb] Remove unused XcodeSDK::SupportsSwift (NFC) (#154572) 2025-08-21 08:55:50 -07:00
Kazu Hirata
035dd1d854 [ADT] Fix a warning
This patch fixes:

  third-party/unittest/googletest/include/gtest/gtest.h:1379:11:
  error: comparison of integers of different signs: 'const unsigned
  long' and 'const int' [-Werror,-Wsign-compare]
2025-08-21 08:49:56 -07:00
Ramkumar Ramachandra
a96b78cf41
[SCEVPatternMatch] Add signed cst match; use in LV (NFC) (#154568)
Add a m_scev_SpecificSInt for matching a sign-extended value, and use it
to improve some code in LoopVectorize.
2025-08-21 15:46:53 +00:00
Guray Ozen
5c36fb3303
[MLIR][NVVM] Improve inline_ptx, add readwrite support (#154358)
Key Features
1. Multiple SSA returns – no struct packing/unpacking required.
2. Automatic struct unpacking – values are directly usable.
3. Readable register mapping
    * {$rwN} → read-write
    * {$roN} → read-only
    * {$woN} → write-only
4. Full read-write support (+ modifier).
5. Simplified operand specification – avoids cryptic
"=r,=r,=f,=f,f,f,0,1" constraints.
6. Predicate support: PTX `@p` predication support

IR Example:
```
%wo0, %wo1 = nvvm.inline_ptx """
 .reg .pred p;
 setp.ge.s32 p,   {$r0}, {$r1};
 selp.s32 {$rw0}, {$r0}, {$r1}, p;
 selp.s32 {$rw1}, {$r0}, {$r1}, p;
 selp.s32 {$w0},  {$r0}, {$r1}, p;
 selp.s32 {$w1},  {$r0}, {$r1}, p;
""" ro(%a, %b : f32, f32) rw(%c, %d : i32, i32) -> f32, f32
```

After lowering
```
 %0 = llvm.inline_asm has_side_effects asm_dialect = att
 "{
                              .reg .pred p;\
                              setp.ge.s32 p, $4, $5;   \
                              selp.s32   $0, $4, $5, p;\
                              selp.s32   $1, $4, $5, p;\
                              selp.s32   $2, $4, $5, p;\
                              selp.s32   $3, $4, $5, p;\
   }"
   "=r,=r,=f,=f,f,f,0,1"
   %c500_i32, %c400_i32, %cst, %cst_0
   : (i32, i32, f32, f32)
   -> !llvm.struct<(i32, i32, f32, f32)>

 %1 = llvm.extractvalue %0 : !llvm.struct<(i32, i32, f32, f32)>
 %2 = llvm.extractvalue %0 : !llvm.struct<(i32, i32, f32, f32)>
 %3 = llvm.extractvalue %0 : !llvm.struct<(i32, i32, f32, f32)>
 %4 = llvm.extractvalue %0 : !llvm.struct<(i32, i32, f32, f32)>

 // Unpacked result from nvvm.inline_ptx
 %5 = arith.addi %1, %2 : i32
 // read only
 %6 = arith.addf %cst, %cst_0 : f32
 // write only
 %7 = arith.addf %3, %4 : f32
```
2025-08-21 17:42:18 +02:00
Florian Hahn
1b0b59ae43
[InstComb] Fold inttoptr (add (ptrtoint %B), %O) -> GEP for ICMP users. (#153421)
Replace inttoptr (add (ptrtoint %B), %O) with (getelementptr i8, %B, %o)
if all users are ICmp instruction, which in turn means only the address
value is compared. We should be able to do this, if the src pointer,
the integer type and the destination pointer types have the same
bitwidth and address space.

A common source of such (inttoptr (add (ptrtoint %B), %O)) is from
various iterations in libc++.

In practice this triggers in a number of files in Clang and various open
source projects, including cppcheck, diamond, llama and more.

Alive2 Proof with constant offset: https://alive2.llvm.org/ce/z/K_5N_B

PR: https://github.com/llvm/llvm-project/pull/153421
2025-08-21 16:36:25 +01:00
Jay Foad
0594bad039
[AMDGPU] Remove "using namespace" from a header. NFC. (#154776) 2025-08-21 16:29:43 +01:00
Chao Chen
68d6866428
[mlir][XeGPU] add WgToSg distribution pattern for load_matrix and store_matrix. (#154403) 2025-08-21 10:02:45 -05:00
Renato Golin
32a5adbd42
[MLIR][Linalg] Rename convolution pass (#154400)
Rename the pass `LinalgNamedOpConversionPass` to
`SimplifyDepthwiseConvPass` to avoid conflating it with the new
morphisms we are creating between the norms.
2025-08-21 15:57:16 +01:00
Steven Perron
a53e73e6ef
[SPIRV][HLSL] Add DXC compatibility option for extension (#151554)
The default behaviour in DXC is to allow all extesions the compiler
knows about. We did the same in clang: all extensions that clang knows
about. However, this causes the shader to use different extensions
because the two compilers have different sets of extensions.

To avoid using a new extension when moving from DXC to Clang, we add the
special DXC suboptions to `-fspv-extension`. If `-fspv-extension=DXC` is
used, then the available extensions will be those available in DXC.

---------

Co-authored-by: Chris B <beanz@abolishcrlf.org>
2025-08-21 14:43:29 +00:00
Florian Hahn
cfef05e69c
[InstCombine] Add tests for (inttoptr (add (ptrtoint %Base), %Offset)).
Precommit tests for https://github.com/llvm/llvm-project/pull/153421.
2025-08-21 15:42:39 +01:00
jyli0116
dbadab96eb
[GlobalISel] Support saturated truncate (#150219)
Implements combining and legalization of G_TRUNC_SSAT_S, G_TRUNC_SSAT_U,
and G_TRUNC_USAT_U, which where previously added to SDAG with the below
patterns:

```
truncate(smin(smax(x, C1), C2)) -> trunc_ssat_s(x)
truncate(smax(smin(x, C2), C1)) -> trunc_ssat_s(x)

truncate(smax(smin(x, C), 0)) -> trunc_ssat_u(x)
truncate(smin(smax(x, 0), C)) -> trunc_ssat_u(x)
truncate(umin(smax(x, 0), C)) -> trunc_ssat_u(x)

truncate(umin(x, C)) -> trunc_usat_u(x)
```
2025-08-21 15:37:53 +01:00
Timm Baeder
3f97736181
[clang][bytecode] Implement ia32_select* builtins (#154758) 2025-08-21 16:34:57 +02:00
Aaron Ballman
17eb05ddd3
Revert "[C++] Expose nullptr_t from stddef.h in C++ mode" (#154767)
Reverts llvm/llvm-project#154599

It seems to be causing staging failures:
    https://lab.llvm.org/staging/#/builders/192/builds/1329
    https://lab.llvm.org/staging/#/builders/192/builds/1330
2025-08-21 10:05:41 -04:00
Guray Ozen
3d41197d68
[MLIR] Introduce RemarkEngine + pluggable remark streaming (YAML/Bitstream) (#152474)
This PR implements structured, tooling-friendly optimization remarks
with zero cost unless enabled. It implements:
- `RemarkEngine` collects finalized remarks within `MLIRContext`.
- `MLIRRemarkStreamerBase` abstract class streams them to a backend.
- Backends: `MLIRLLVMRemarkStreamer` (bridges to llvm::remarks →
YAML/Bitstream) or your own custom streamer.
- Optional mirroring to DiagnosticEngine (printAsEmitRemarks +
categories).
- Off by default; no behavior change unless enabled. Thread-safe;
ordering best-effort.


## Overview

```
Passes (reportOptimization*)
         │
         ▼
+-------------------+
|  RemarkEngine     |   collects
+-------------------+
     │         │
     │ mirror  │ stream
     ▼         ▼
emitRemark    MLIRRemarkStreamerBase (abstract)
                   │
                   ├── MLIRLLVMRemarkStreamer → llvm::remarks → YAML | Bitstream
                   └── CustomStreamer → your sink
```

## Enable Remark engine and Plug LLVM's Remark streamer
```
// Enable once per MLIRContext. This uses `MLIRLLVMRemarkStreamer`
mlir::remark::enableOptimizationRemarksToFile(
    ctx, path, llvm::remarks::Format::YAML, cats);
```

## API to emit remark
```
// Emit from a pass
 remark::passed(loc, categoryVectorizer, myPassname1)
        << "vectorized loop";

remark::missed(loc, categoryUnroll, "MyPass")
        << remark::reason("not profitable at this size")   // Creates structured reason arg
        << remark::suggest("increase unroll factor to >=4");   // Creates structured suggestion arg

remark::passed(loc, categoryVectorizer, myPassname1)
        << "vectorized loop" 
        << remark::metric("tripCount", 128);                // Create structured metric on-the-fly
```
2025-08-21 16:02:31 +02:00
Jay Foad
5d4aa87ca5 [AMDGPU] Remove redundant isAMDGCN check. NFC. 2025-08-21 14:54:53 +01:00
Bjorn Pettersson
e21b0dd819
[llvm-lit] Second attempt to fix print-relative-path.py
This is a fixup for #154317
2025-08-21 15:47:49 +02:00
Luke Lau
42cf9c60d7
[RISCV] Mark Sub/AddChainWithSubs as legal reduction types (#154753)
We used to vectorize these scalably but after #147026 they were split
out from RecurKind::Add into their own RecurKinds, and we didn't mark
them as supported in isLegalToVectorizeReduction.

This caused the loop vectorizer to drop the scalable VPlan because it
thinks the reductions will be scalarized.

This fixes it by just marking them as supported.

Fixes #154554
2025-08-21 21:43:48 +08:00
759 changed files with 71148 additions and 19235 deletions

View File

@ -60,7 +60,8 @@ cmake -S "${MONOREPO_ROOT}"/llvm -B "${BUILD_DIR}" \
-D MLIR_ENABLE_BINDINGS_PYTHON=ON \
-D LLDB_ENABLE_PYTHON=ON \
-D LLDB_ENFORCE_STRICT_TEST_REQUIREMENTS=ON \
-D CMAKE_INSTALL_PREFIX="${INSTALL_DIR}"
-D CMAKE_INSTALL_PREFIX="${INSTALL_DIR}" \
-D CMAKE_EXE_LINKER_FLAGS="-no-pie"
start-group "ninja"

View File

@ -138,6 +138,12 @@
Dump function CFGs to graphviz format after each stage;enable '-print-loops'
for color-coded blocks
- `--dump-dot-func=<func1,func2,func3...>`
Dump function CFGs to graphviz format for specified functions only;
takes function name patterns (regex supported). Note: C++ function names
must be passed using their mangled names
- `--dump-linux-exceptions`
Dump Linux kernel exception table

View File

@ -15,6 +15,12 @@
#include "llvm/Support/CommandLine.h"
namespace llvm {
namespace bolt {
class BinaryFunction;
}
} // namespace llvm
namespace opts {
enum HeatmapModeKind {
@ -100,6 +106,9 @@ extern llvm::cl::opt<unsigned> Verbosity;
/// Return true if we should process all functions in the binary.
bool processAllFunctions();
/// Return true if we should dump dot graphs for the given function.
bool shouldDumpDot(const llvm::bolt::BinaryFunction &Function);
enum GadgetScannerKind { GS_PACRET, GS_PAUTH, GS_ALL };
extern llvm::cl::bits<GadgetScannerKind> GadgetScannersToRun;

View File

@ -52,6 +52,7 @@ namespace opts {
extern cl::opt<bool> PrintAll;
extern cl::opt<bool> PrintDynoStats;
extern cl::opt<bool> DumpDotAll;
extern bool shouldDumpDot(const bolt::BinaryFunction &Function);
extern cl::opt<std::string> AsmDump;
extern cl::opt<bolt::PLTCall::OptType> PLT;
extern cl::opt<bolt::IdenticalCodeFolding::ICFLevel, false,
@ -340,7 +341,7 @@ Error BinaryFunctionPassManager::runPasses() {
Function.print(BC.outs(), Message);
if (opts::DumpDotAll)
if (opts::shouldDumpDot(Function))
Function.dumpGraphForPass(PassIdName);
}
}

View File

@ -115,6 +115,35 @@ cl::opt<bool> DumpDotAll(
"enable '-print-loops' for color-coded blocks"),
cl::Hidden, cl::cat(BoltCategory));
cl::list<std::string> DumpDotFunc(
"dump-dot-func", cl::CommaSeparated,
cl::desc(
"dump function CFGs to graphviz format for specified functions only;"
"takes function name patterns (regex supported)"),
cl::value_desc("func1,func2,func3,..."), cl::Hidden, cl::cat(BoltCategory));
bool shouldDumpDot(const bolt::BinaryFunction &Function) {
// If dump-dot-all is enabled, dump all functions
if (DumpDotAll)
return !Function.isIgnored();
// If no specific functions specified in dump-dot-func, don't dump any
if (DumpDotFunc.empty())
return false;
if (Function.isIgnored())
return false;
// Check if function matches any of the specified patterns
for (const std::string &Name : DumpDotFunc) {
if (Function.hasNameRegex(Name)) {
return true;
}
}
return false;
}
static cl::list<std::string>
ForceFunctionNames("funcs",
cl::CommaSeparated,
@ -3569,7 +3598,7 @@ void RewriteInstance::postProcessFunctions() {
if (opts::PrintAll || opts::PrintCFG)
Function.print(BC->outs(), "after building cfg");
if (opts::DumpDotAll)
if (opts::shouldDumpDot(Function))
Function.dumpGraphForPass("00_build-cfg");
if (opts::PrintLoopInfo) {

View File

@ -0,0 +1,24 @@
#include <iostream>
// Multiple functions to test selective dumping
int add(int a, int b) { return a + b; }
int multiply(int a, int b) { return a * b; }
int main_helper() {
std::cout << "Helper function" << std::endl;
return 42;
}
int main_secondary() { return add(5, 3); }
void other_function() { std::cout << "Other function" << std::endl; }
int main() {
int result = add(10, 20);
result = multiply(result, 2);
main_helper();
main_secondary();
other_function();
return result;
}

View File

@ -0,0 +1,52 @@
# Test the --dump-dot-func option with multiple functions
# (includes tests for both mangled/unmangled names)
RUN: %clang++ %p/Inputs/multi-func.cpp -o %t.exe -Wl,-q
# Test 1: --dump-dot-func with specific function name (mangled)
RUN: llvm-bolt %t.exe -o %t.bolt1 --dump-dot-func=_Z3addii -v=1 2>&1 | FileCheck %s --check-prefix=ADD
# Test 2: --dump-dot-func with regex pattern (main.*)
RUN: llvm-bolt %t.exe -o %t.bolt2 --dump-dot-func="main.*" -v=1 2>&1 | FileCheck %s --check-prefix=MAIN-REGEX
# Test 3: --dump-dot-func with multiple specific functions (mangled names)
RUN: llvm-bolt %t.exe -o %t.bolt3 --dump-dot-func=_Z3addii,_Z8multiplyii -v=1 2>&1 | FileCheck %s --check-prefix=MULTI
# Test 4: No option specified should create no dot files
RUN: llvm-bolt %t.exe -o %t.bolt4 2>&1 | FileCheck %s --check-prefix=NONE
# Test 5: --dump-dot-func with non-existent function
RUN: llvm-bolt %t.exe -o %t.bolt5 --dump-dot-func=nonexistent -v=1 2>&1 | FileCheck %s --check-prefix=NONEXISTENT
# Test 6: Backward compatibility - --dump-dot-all should still work
RUN: llvm-bolt %t.exe -o %t.bolt6 --dump-dot-all -v=1 2>&1 | FileCheck %s --check-prefix=ALL
# Test 7: Test with unmangled function name (main function)
RUN: llvm-bolt %t.exe -o %t.bolt7 --dump-dot-func=main -v=1 2>&1 | FileCheck %s --check-prefix=MAIN-UNMANGLED
# Check that specific functions are dumped
ADD: BOLT-INFO: dumping CFG to _Z3addii-00_build-cfg.dot
ADD-NOT: BOLT-INFO: dumping CFG to main-00_build-cfg.dot
ADD-NOT: BOLT-INFO: dumping CFG to _Z8multiplyii-00_build-cfg.dot
ADD-NOT: BOLT-INFO: dumping CFG to _Z11main_helperv-00_build-cfg.dot
MAIN-REGEX-DAG: BOLT-INFO: dumping CFG to main-00_build-cfg.dot
MAIN-REGEX-NOT: BOLT-INFO: dumping CFG to _Z3addii-00_build-cfg.dot
MAIN-REGEX-NOT: BOLT-INFO: dumping CFG to _Z8multiplyii-00_build-cfg.dot
MULTI-DAG: BOLT-INFO: dumping CFG to _Z3addii-00_build-cfg.dot
MULTI-DAG: BOLT-INFO: dumping CFG to _Z8multiplyii-00_build-cfg.dot
MULTI-NOT: BOLT-INFO: dumping CFG to main-00_build-cfg.dot
MULTI-NOT: BOLT-INFO: dumping CFG to _Z11main_helperv-00_build-cfg.dot
# Should be no dumping messages when no option is specified
NONE-NOT: BOLT-INFO: dumping CFG
# Should be no dumping messages for non-existent function
NONEXISTENT-NOT: BOLT-INFO: dumping CFG
ALL: BOLT-INFO: dumping CFG to main-00_build-cfg.dot
MAIN-UNMANGLED: BOLT-INFO: dumping CFG to main-00_build-cfg.dot
MAIN-UNMANGLED-NOT: BOLT-INFO: dumping CFG to _Z3addii-00_build-cfg.dot
MAIN-UNMANGLED-NOT: BOLT-INFO: dumping CFG to _Z8multiplyii-00_build-cfg.dot

View File

@ -1575,6 +1575,10 @@ template <typename T, std::size_t N = SmallDataStructureSize>
using ParamToSmallSetMap =
llvm::DenseMap<const ParmVarDecl *, llvm::SmallSet<T, N>>;
template <typename T, std::size_t N = SmallDataStructureSize>
using ParamToSmallPtrSetMap =
llvm::DenseMap<const ParmVarDecl *, llvm::SmallPtrSet<T, N>>;
/// Returns whether the sets mapped to the two elements in the map have at
/// least one element in common.
template <typename MapTy, typename ElemTy>
@ -1699,7 +1703,7 @@ public:
/// Implements the heuristic that marks two parameters related if the same
/// member is accessed (referred to) inside the current function's body.
class AccessedSameMemberOf {
ParamToSmallSetMap<const Decl *> AccessedMembers;
ParamToSmallPtrSetMap<const Decl *> AccessedMembers;
public:
void setup(const FunctionDecl *FD) {

View File

@ -15,14 +15,12 @@ using namespace clang::ast_matchers;
namespace clang::tidy::bugprone {
namespace {
// Determine if the result of an expression is "stored" in some way.
// It is true if the value is stored into a variable or used as initialization
// or passed to a function or constructor.
// For this use case compound assignments are not counted as a "store" (the 'E'
// expression should have pointer type).
bool isExprValueStored(const Expr *E, ASTContext &C) {
static bool isExprValueStored(const Expr *E, ASTContext &C) {
E = E->IgnoreParenCasts();
// Get first non-paren, non-cast parent.
ParentMapContext &PMap = C.getParentMapContext();
@ -49,6 +47,8 @@ bool isExprValueStored(const Expr *E, ASTContext &C) {
return isa<CallExpr, CXXConstructExpr>(ParentE);
}
namespace {
AST_MATCHER_P(CXXTryStmt, hasHandlerFor,
ast_matchers::internal::Matcher<QualType>, InnerMatcher) {
for (unsigned NH = Node.getNumHandlers(), I = 0; I < NH; ++I) {

View File

@ -14,10 +14,8 @@ using namespace clang::ast_matchers;
namespace clang::tidy::bugprone {
namespace {
bool isConcatenatedLiteralsOnPurpose(ASTContext *Ctx,
const StringLiteral *Lit) {
static bool isConcatenatedLiteralsOnPurpose(ASTContext *Ctx,
const StringLiteral *Lit) {
// String literals surrounded by parentheses are assumed to be on purpose.
// i.e.: const char* Array[] = { ("a" "b" "c"), "d", [...] };
@ -58,6 +56,8 @@ bool isConcatenatedLiteralsOnPurpose(ASTContext *Ctx,
return false;
}
namespace {
AST_MATCHER_P(StringLiteral, isConcatenatedLiteral, unsigned,
MaxConcatenatedTokens) {
return Node.getNumConcatenated() > 1 &&

View File

@ -46,7 +46,9 @@ enum class ConversionKind {
ToLongDouble
};
ConversionKind classifyConversionFunc(const FunctionDecl *FD) {
} // namespace
static ConversionKind classifyConversionFunc(const FunctionDecl *FD) {
return llvm::StringSwitch<ConversionKind>(FD->getName())
.Cases("atoi", "atol", ConversionKind::ToInt)
.Case("atoll", ConversionKind::ToLongInt)
@ -54,8 +56,8 @@ ConversionKind classifyConversionFunc(const FunctionDecl *FD) {
.Default(ConversionKind::None);
}
ConversionKind classifyFormatString(StringRef Fmt, const LangOptions &LO,
const TargetInfo &TI) {
static ConversionKind classifyFormatString(StringRef Fmt, const LangOptions &LO,
const TargetInfo &TI) {
// Scan the format string for the first problematic format specifier, then
// report that as the conversion type. This will miss additional conversion
// specifiers, but that is acceptable behavior.
@ -128,7 +130,7 @@ ConversionKind classifyFormatString(StringRef Fmt, const LangOptions &LO,
return H.get();
}
StringRef classifyConversionType(ConversionKind K) {
static StringRef classifyConversionType(ConversionKind K) {
switch (K) {
case ConversionKind::None:
llvm_unreachable("Unexpected conversion kind");
@ -148,7 +150,7 @@ StringRef classifyConversionType(ConversionKind K) {
llvm_unreachable("Unknown conversion kind");
}
StringRef classifyReplacement(ConversionKind K) {
static StringRef classifyReplacement(ConversionKind K) {
switch (K) {
case ConversionKind::None:
llvm_unreachable("Unexpected conversion kind");
@ -173,7 +175,6 @@ StringRef classifyReplacement(ConversionKind K) {
}
llvm_unreachable("Unknown conversion kind");
}
} // unnamed namespace
void StrToNumCheck::check(const MatchFinder::MatchResult &Result) {
const auto *Call = Result.Nodes.getNodeAs<CallExpr>("expr");

View File

@ -59,7 +59,9 @@ AST_MATCHER(FunctionDecl, isPlacementOverload) {
return true;
}
OverloadedOperatorKind getCorrespondingOverload(const FunctionDecl *FD) {
} // namespace
static OverloadedOperatorKind getCorrespondingOverload(const FunctionDecl *FD) {
switch (FD->getOverloadedOperator()) {
default:
break;
@ -75,7 +77,7 @@ OverloadedOperatorKind getCorrespondingOverload(const FunctionDecl *FD) {
llvm_unreachable("Not an overloaded allocation operator");
}
const char *getOperatorName(OverloadedOperatorKind K) {
static const char *getOperatorName(OverloadedOperatorKind K) {
switch (K) {
default:
break;
@ -91,13 +93,14 @@ const char *getOperatorName(OverloadedOperatorKind K) {
llvm_unreachable("Not an overloaded allocation operator");
}
bool areCorrespondingOverloads(const FunctionDecl *LHS,
const FunctionDecl *RHS) {
static bool areCorrespondingOverloads(const FunctionDecl *LHS,
const FunctionDecl *RHS) {
return RHS->getOverloadedOperator() == getCorrespondingOverload(LHS);
}
bool hasCorrespondingOverloadInBaseClass(const CXXMethodDecl *MD,
const CXXRecordDecl *RD = nullptr) {
static bool
hasCorrespondingOverloadInBaseClass(const CXXMethodDecl *MD,
const CXXRecordDecl *RD = nullptr) {
if (RD) {
// Check the methods in the given class and accessible to derived classes.
for (const auto *BMD : RD->methods())
@ -124,8 +127,6 @@ bool hasCorrespondingOverloadInBaseClass(const CXXMethodDecl *MD,
return false;
}
} // anonymous namespace
void NewDeleteOverloadsCheck::registerMatchers(MatchFinder *Finder) {
// Match all operator new and operator delete overloads (including the array
// forms). Do not match implicit operators, placement operators, or

View File

@ -395,16 +395,12 @@ void MacroToEnumCallbacks::Endif(SourceLocation Loc, SourceLocation IfLoc) {
--CurrentFile->ConditionScopes;
}
namespace {
template <size_t N>
bool textEquals(const char (&Needle)[N], const char *HayStack) {
static bool textEquals(const char (&Needle)[N], const char *HayStack) {
return StringRef{HayStack, N - 1} == Needle;
}
template <size_t N> size_t len(const char (&)[N]) { return N - 1; }
} // namespace
template <size_t N> static size_t len(const char (&)[N]) { return N - 1; }
void MacroToEnumCallbacks::PragmaDirective(SourceLocation Loc,
PragmaIntroducerKind Introducer) {

View File

@ -16,14 +16,13 @@ using namespace clang::ast_matchers;
namespace clang::tidy::modernize {
namespace {
static constexpr char ConstructorCall[] = "constructorCall";
static constexpr char ResetCall[] = "resetCall";
static constexpr char NewExpression[] = "newExpression";
constexpr char ConstructorCall[] = "constructorCall";
constexpr char ResetCall[] = "resetCall";
constexpr char NewExpression[] = "newExpression";
std::string getNewExprName(const CXXNewExpr *NewExpr, const SourceManager &SM,
const LangOptions &Lang) {
static std::string getNewExprName(const CXXNewExpr *NewExpr,
const SourceManager &SM,
const LangOptions &Lang) {
StringRef WrittenName = Lexer::getSourceText(
CharSourceRange::getTokenRange(
NewExpr->getAllocatedTypeSourceInfo()->getTypeLoc().getSourceRange()),
@ -34,8 +33,6 @@ std::string getNewExprName(const CXXNewExpr *NewExpr, const SourceManager &SM,
return WrittenName.str();
}
} // namespace
const char MakeSmartPtrCheck::PointerType[] = "pointerType";
MakeSmartPtrCheck::MakeSmartPtrCheck(StringRef Name, ClangTidyContext *Context,

View File

@ -19,9 +19,7 @@ using namespace clang::ast_matchers;
namespace clang::tidy::modernize {
namespace {
bool containsEscapes(StringRef HayStack, StringRef Escapes) {
static bool containsEscapes(StringRef HayStack, StringRef Escapes) {
size_t BackSlash = HayStack.find('\\');
if (BackSlash == StringRef::npos)
return false;
@ -35,16 +33,16 @@ bool containsEscapes(StringRef HayStack, StringRef Escapes) {
return true;
}
bool isRawStringLiteral(StringRef Text) {
static bool isRawStringLiteral(StringRef Text) {
// Already a raw string literal if R comes before ".
const size_t QuotePos = Text.find('"');
assert(QuotePos != StringRef::npos);
return (QuotePos > 0) && (Text[QuotePos - 1] == 'R');
}
bool containsEscapedCharacters(const MatchFinder::MatchResult &Result,
const StringLiteral *Literal,
const CharsBitSet &DisallowedChars) {
static bool containsEscapedCharacters(const MatchFinder::MatchResult &Result,
const StringLiteral *Literal,
const CharsBitSet &DisallowedChars) {
// FIXME: Handle L"", u8"", u"" and U"" literals.
if (!Literal->isOrdinary())
return false;
@ -64,14 +62,12 @@ bool containsEscapedCharacters(const MatchFinder::MatchResult &Result,
return containsEscapes(Text, R"('\"?x01)");
}
bool containsDelimiter(StringRef Bytes, const std::string &Delimiter) {
static bool containsDelimiter(StringRef Bytes, const std::string &Delimiter) {
return Bytes.find(Delimiter.empty()
? std::string(R"lit()")lit")
: (")" + Delimiter + R"(")")) != StringRef::npos;
}
} // namespace
RawStringLiteralCheck::RawStringLiteralCheck(StringRef Name,
ClangTidyContext *Context)
: ClangTidyCheck(Name, Context),

View File

@ -29,12 +29,13 @@
using namespace clang::ast_matchers;
namespace clang::tidy::objc {
namespace {
static constexpr StringRef WeakText = "__weak";
static constexpr StringRef StrongText = "__strong";
static constexpr StringRef UnsafeUnretainedText = "__unsafe_unretained";
namespace {
/// Matches ObjCIvarRefExpr, DeclRefExpr, or MemberExpr that reference
/// Objective-C object (or block) variables or fields whose object lifetimes
/// are not __unsafe_unretained.
@ -49,6 +50,8 @@ AST_POLYMORPHIC_MATCHER(isObjCManagedLifetime,
QT.getQualifiers().getObjCLifetime() > Qualifiers::OCL_ExplicitNone;
}
} // namespace
static std::optional<FixItHint>
fixItHintReplacementForOwnershipString(StringRef Text, CharSourceRange Range,
StringRef Ownership) {
@ -93,8 +96,6 @@ fixItHintForVarDecl(const VarDecl *VD, const SourceManager &SM,
return FixItHint::CreateInsertion(Range.getBegin(), "__unsafe_unretained ");
}
} // namespace
void NSInvocationArgumentLifetimeCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(
traverse(

View File

@ -27,11 +27,14 @@ enum NamingStyle {
CategoryProperty = 2,
};
} // namespace
/// For now we will only fix 'CamelCase' or 'abc_CamelCase' property to
/// 'camelCase' or 'abc_camelCase'. For other cases the users need to
/// come up with a proper name by their own.
/// FIXME: provide fix for snake_case to snakeCase
FixItHint generateFixItHint(const ObjCPropertyDecl *Decl, NamingStyle Style) {
static FixItHint generateFixItHint(const ObjCPropertyDecl *Decl,
NamingStyle Style) {
auto Name = Decl->getName();
auto NewName = Decl->getName().str();
size_t Index = 0;
@ -50,7 +53,7 @@ FixItHint generateFixItHint(const ObjCPropertyDecl *Decl, NamingStyle Style) {
return {};
}
std::string validPropertyNameRegex(bool UsedInMatcher) {
static std::string validPropertyNameRegex(bool UsedInMatcher) {
// Allow any of these names:
// foo
// fooBar
@ -72,13 +75,13 @@ std::string validPropertyNameRegex(bool UsedInMatcher) {
return StartMatcher + "([a-z]|[A-Z][A-Z0-9])[a-z0-9A-Z]*$";
}
bool hasCategoryPropertyPrefix(llvm::StringRef PropertyName) {
static bool hasCategoryPropertyPrefix(llvm::StringRef PropertyName) {
auto RegexExp =
llvm::Regex("^[a-zA-Z][a-zA-Z0-9]*_[a-zA-Z0-9][a-zA-Z0-9_]+$");
return RegexExp.match(PropertyName);
}
bool prefixedPropertyNameValid(llvm::StringRef PropertyName) {
static bool prefixedPropertyNameValid(llvm::StringRef PropertyName) {
size_t Start = PropertyName.find_first_of('_');
assert(Start != llvm::StringRef::npos && Start + 1 < PropertyName.size());
auto Prefix = PropertyName.substr(0, Start);
@ -88,7 +91,6 @@ bool prefixedPropertyNameValid(llvm::StringRef PropertyName) {
auto RegexExp = llvm::Regex(llvm::StringRef(validPropertyNameRegex(false)));
return RegexExp.match(PropertyName.substr(Start + 1));
}
} // namespace
void PropertyDeclarationCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(objcPropertyDecl(

View File

@ -17,7 +17,6 @@
#include <optional>
namespace clang::tidy::performance {
namespace {
using namespace ::clang::ast_matchers;
using llvm::StringRef;
@ -30,8 +29,8 @@ static constexpr StringRef MethodDeclId = "methodDecl";
static constexpr StringRef FunctionDeclId = "functionDecl";
static constexpr StringRef OldVarDeclId = "oldVarDecl";
void recordFixes(const VarDecl &Var, ASTContext &Context,
DiagnosticBuilder &Diagnostic) {
static void recordFixes(const VarDecl &Var, ASTContext &Context,
DiagnosticBuilder &Diagnostic) {
Diagnostic << utils::fixit::changeVarDeclToReference(Var, Context);
if (!Var.getType().isLocalConstQualified()) {
if (std::optional<FixItHint> Fix = utils::fixit::addQualifierToVarDecl(
@ -40,8 +39,8 @@ void recordFixes(const VarDecl &Var, ASTContext &Context,
}
}
std::optional<SourceLocation> firstLocAfterNewLine(SourceLocation Loc,
SourceManager &SM) {
static std::optional<SourceLocation> firstLocAfterNewLine(SourceLocation Loc,
SourceManager &SM) {
bool Invalid = false;
const char *TextAfter = SM.getCharacterData(Loc, &Invalid);
if (Invalid) {
@ -51,8 +50,8 @@ std::optional<SourceLocation> firstLocAfterNewLine(SourceLocation Loc,
return Loc.getLocWithOffset(TextAfter[Offset] == '\0' ? Offset : Offset + 1);
}
void recordRemoval(const DeclStmt &Stmt, ASTContext &Context,
DiagnosticBuilder &Diagnostic) {
static void recordRemoval(const DeclStmt &Stmt, ASTContext &Context,
DiagnosticBuilder &Diagnostic) {
auto &SM = Context.getSourceManager();
// Attempt to remove trailing comments as well.
auto Tok = utils::lexer::findNextTokenSkippingComments(Stmt.getEndLoc(), SM,
@ -74,6 +73,8 @@ void recordRemoval(const DeclStmt &Stmt, ASTContext &Context,
}
}
namespace {
AST_MATCHER_FUNCTION_P(StatementMatcher,
isRefReturningMethodCallWithConstOverloads,
std::vector<StringRef>, ExcludedContainerTypes) {
@ -130,6 +131,8 @@ AST_MATCHER_FUNCTION_P(StatementMatcher, initializerReturnsReferenceToConst,
hasUnaryOperand(OldVarDeclRef)))));
}
} // namespace
// This checks that the variable itself is only used as const, and also makes
// sure that it does not reference another variable that could be modified in
// the BlockStmt. It does this by checking the following:
@ -180,13 +183,13 @@ static bool isInitializingVariableImmutable(
return false;
}
bool isVariableUnused(const VarDecl &Var, const Stmt &BlockStmt,
ASTContext &Context) {
static bool isVariableUnused(const VarDecl &Var, const Stmt &BlockStmt,
ASTContext &Context) {
return allDeclRefExprs(Var, BlockStmt, Context).empty();
}
const SubstTemplateTypeParmType *getSubstitutedType(const QualType &Type,
ASTContext &Context) {
static const SubstTemplateTypeParmType *
getSubstitutedType(const QualType &Type, ASTContext &Context) {
auto Matches = match(
qualType(anyOf(substTemplateTypeParmType().bind("subst"),
hasDescendant(substTemplateTypeParmType().bind("subst")))),
@ -194,9 +197,9 @@ const SubstTemplateTypeParmType *getSubstitutedType(const QualType &Type,
return selectFirst<SubstTemplateTypeParmType>("subst", Matches);
}
bool differentReplacedTemplateParams(const QualType &VarType,
const QualType &InitializerType,
ASTContext &Context) {
static bool differentReplacedTemplateParams(const QualType &VarType,
const QualType &InitializerType,
ASTContext &Context) {
if (const SubstTemplateTypeParmType *VarTmplType =
getSubstitutedType(VarType, Context)) {
if (const SubstTemplateTypeParmType *InitializerTmplType =
@ -212,8 +215,8 @@ bool differentReplacedTemplateParams(const QualType &VarType,
return false;
}
QualType constructorArgumentType(const VarDecl *OldVar,
const BoundNodes &Nodes) {
static QualType constructorArgumentType(const VarDecl *OldVar,
const BoundNodes &Nodes) {
if (OldVar) {
return OldVar->getType();
}
@ -224,8 +227,6 @@ QualType constructorArgumentType(const VarDecl *OldVar,
return MethodDecl->getReturnType();
}
} // namespace
UnnecessaryCopyInitialization::UnnecessaryCopyInitialization(
StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context),

View File

@ -21,16 +21,14 @@ using namespace clang::ast_matchers;
namespace clang::tidy::performance {
namespace {
std::string paramNameOrIndex(StringRef Name, size_t Index) {
static std::string paramNameOrIndex(StringRef Name, size_t Index) {
return (Name.empty() ? llvm::Twine('#') + llvm::Twine(Index + 1)
: llvm::Twine('\'') + Name + llvm::Twine('\''))
.str();
}
bool hasLoopStmtAncestor(const DeclRefExpr &DeclRef, const Decl &Decl,
ASTContext &Context) {
static bool hasLoopStmtAncestor(const DeclRefExpr &DeclRef, const Decl &Decl,
ASTContext &Context) {
auto Matches = match(
traverse(TK_AsIs,
decl(forEachDescendant(declRefExpr(
@ -41,8 +39,6 @@ bool hasLoopStmtAncestor(const DeclRefExpr &DeclRef, const Decl &Decl,
return Matches.empty();
}
} // namespace
UnnecessaryValueParamCheck::UnnecessaryValueParamCheck(
StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context),

View File

@ -122,15 +122,15 @@ AST_MATCHER(EnumDecl, hasSequentialInitialValues) {
return !AllEnumeratorsArePowersOfTwo;
}
std::string getName(const EnumDecl *Decl) {
} // namespace
static std::string getName(const EnumDecl *Decl) {
if (!Decl->getDeclName())
return "<unnamed>";
return Decl->getQualifiedNameAsString();
}
} // namespace
EnumInitialValueCheck::EnumInitialValueCheck(StringRef Name,
ClangTidyContext *Context)
: ClangTidyCheck(Name, Context),

View File

@ -144,6 +144,8 @@ struct CognitiveComplexity final {
void account(SourceLocation Loc, unsigned short Nesting, Criteria C);
};
} // namespace
// All the possible messages that can be output. The choice of the message
// to use is based of the combination of the CognitiveComplexity::Criteria.
// It would be nice to have it in CognitiveComplexity struct, but then it is
@ -163,23 +165,27 @@ static const std::array<const StringRef, 4> Msgs = {{
}};
// Criteria is a bitset, thus a few helpers are needed.
CognitiveComplexity::Criteria operator|(CognitiveComplexity::Criteria LHS,
CognitiveComplexity::Criteria RHS) {
static CognitiveComplexity::Criteria
operator|(CognitiveComplexity::Criteria LHS,
CognitiveComplexity::Criteria RHS) {
return static_cast<CognitiveComplexity::Criteria>(llvm::to_underlying(LHS) |
llvm::to_underlying(RHS));
}
CognitiveComplexity::Criteria operator&(CognitiveComplexity::Criteria LHS,
CognitiveComplexity::Criteria RHS) {
static CognitiveComplexity::Criteria
operator&(CognitiveComplexity::Criteria LHS,
CognitiveComplexity::Criteria RHS) {
return static_cast<CognitiveComplexity::Criteria>(llvm::to_underlying(LHS) &
llvm::to_underlying(RHS));
}
CognitiveComplexity::Criteria &operator|=(CognitiveComplexity::Criteria &LHS,
CognitiveComplexity::Criteria RHS) {
static CognitiveComplexity::Criteria &
operator|=(CognitiveComplexity::Criteria &LHS,
CognitiveComplexity::Criteria RHS) {
LHS = operator|(LHS, RHS);
return LHS;
}
CognitiveComplexity::Criteria &operator&=(CognitiveComplexity::Criteria &LHS,
CognitiveComplexity::Criteria RHS) {
static CognitiveComplexity::Criteria &
operator&=(CognitiveComplexity::Criteria &LHS,
CognitiveComplexity::Criteria RHS) {
LHS = operator&(LHS, RHS);
return LHS;
}
@ -199,6 +205,8 @@ void CognitiveComplexity::account(SourceLocation Loc, unsigned short Nesting,
Total += Increase;
}
namespace {
class FunctionASTVisitor final
: public RecursiveASTVisitor<FunctionASTVisitor> {
using Base = RecursiveASTVisitor<FunctionASTVisitor>;

View File

@ -41,9 +41,11 @@ AST_MATCHER(Stmt, isNULLMacroExpansion) {
return isNULLMacroExpansion(&Node, Finder->getASTContext());
}
StringRef getZeroLiteralToCompareWithForType(CastKind CastExprKind,
QualType Type,
ASTContext &Context) {
} // namespace
static StringRef getZeroLiteralToCompareWithForType(CastKind CastExprKind,
QualType Type,
ASTContext &Context) {
switch (CastExprKind) {
case CK_IntegralToBoolean:
return Type->isUnsignedIntegerType() ? "0u" : "0";
@ -62,15 +64,15 @@ StringRef getZeroLiteralToCompareWithForType(CastKind CastExprKind,
}
}
bool isUnaryLogicalNotOperator(const Stmt *Statement) {
static bool isUnaryLogicalNotOperator(const Stmt *Statement) {
const auto *UnaryOperatorExpr = dyn_cast<UnaryOperator>(Statement);
return UnaryOperatorExpr && UnaryOperatorExpr->getOpcode() == UO_LNot;
}
void fixGenericExprCastToBool(DiagnosticBuilder &Diag,
const ImplicitCastExpr *Cast, const Stmt *Parent,
ASTContext &Context,
bool UseUpperCaseLiteralSuffix) {
static void fixGenericExprCastToBool(DiagnosticBuilder &Diag,
const ImplicitCastExpr *Cast,
const Stmt *Parent, ASTContext &Context,
bool UseUpperCaseLiteralSuffix) {
// In case of expressions like (! integer), we should remove the redundant not
// operator and use inverted comparison (integer == 0).
bool InvertComparison =
@ -133,8 +135,8 @@ void fixGenericExprCastToBool(DiagnosticBuilder &Diag,
Diag << FixItHint::CreateInsertion(EndLoc, EndLocInsertion);
}
StringRef getEquivalentBoolLiteralForExpr(const Expr *Expression,
ASTContext &Context) {
static StringRef getEquivalentBoolLiteralForExpr(const Expr *Expression,
ASTContext &Context) {
if (isNULLMacroExpansion(Expression, Context)) {
return "false";
}
@ -161,7 +163,7 @@ StringRef getEquivalentBoolLiteralForExpr(const Expr *Expression,
return {};
}
bool needsSpacePrefix(SourceLocation Loc, ASTContext &Context) {
static bool needsSpacePrefix(SourceLocation Loc, ASTContext &Context) {
SourceRange PrefixRange(Loc.getLocWithOffset(-1), Loc);
StringRef SpaceBeforeStmtStr = Lexer::getSourceText(
CharSourceRange::getCharRange(PrefixRange), Context.getSourceManager(),
@ -173,9 +175,10 @@ bool needsSpacePrefix(SourceLocation Loc, ASTContext &Context) {
return !AllowedCharacters.contains(SpaceBeforeStmtStr.back());
}
void fixGenericExprCastFromBool(DiagnosticBuilder &Diag,
const ImplicitCastExpr *Cast,
ASTContext &Context, StringRef OtherType) {
static void fixGenericExprCastFromBool(DiagnosticBuilder &Diag,
const ImplicitCastExpr *Cast,
ASTContext &Context,
StringRef OtherType) {
if (!Context.getLangOpts().CPlusPlus) {
Diag << FixItHint::CreateInsertion(Cast->getBeginLoc(),
(Twine("(") + OtherType + ")").str());
@ -200,8 +203,9 @@ void fixGenericExprCastFromBool(DiagnosticBuilder &Diag,
}
}
StringRef getEquivalentForBoolLiteral(const CXXBoolLiteralExpr *BoolLiteral,
QualType DestType, ASTContext &Context) {
static StringRef
getEquivalentForBoolLiteral(const CXXBoolLiteralExpr *BoolLiteral,
QualType DestType, ASTContext &Context) {
// Prior to C++11, false literal could be implicitly converted to pointer.
if (!Context.getLangOpts().CPlusPlus11 &&
(DestType->isPointerType() || DestType->isMemberPointerType()) &&
@ -222,8 +226,8 @@ StringRef getEquivalentForBoolLiteral(const CXXBoolLiteralExpr *BoolLiteral,
return BoolLiteral->getValue() ? "1" : "0";
}
bool isCastAllowedInCondition(const ImplicitCastExpr *Cast,
ASTContext &Context) {
static bool isCastAllowedInCondition(const ImplicitCastExpr *Cast,
ASTContext &Context) {
std::queue<const Stmt *> Q;
Q.push(Cast);
@ -251,8 +255,6 @@ bool isCastAllowedInCondition(const ImplicitCastExpr *Cast,
return false;
}
} // anonymous namespace
ImplicitBoolConversionCheck::ImplicitBoolConversionCheck(
StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context),

View File

@ -28,8 +28,11 @@ AST_MATCHER_P(QualType, hasUnqualifiedType,
enum class Qualifier { Const, Volatile, Restrict };
std::optional<Token> findQualToken(const VarDecl *Decl, Qualifier Qual,
const MatchFinder::MatchResult &Result) {
} // namespace
static std::optional<Token>
findQualToken(const VarDecl *Decl, Qualifier Qual,
const MatchFinder::MatchResult &Result) {
// Since either of the locs can be in a macro, use `makeFileCharRange` to be
// sure that we have a consistent `CharSourceRange`, located entirely in the
// source file.
@ -58,7 +61,7 @@ std::optional<Token> findQualToken(const VarDecl *Decl, Qualifier Qual,
*Result.SourceManager);
}
std::optional<SourceRange>
static std::optional<SourceRange>
getTypeSpecifierLocation(const VarDecl *Var,
const MatchFinder::MatchResult &Result) {
SourceRange TypeSpecifier(
@ -73,8 +76,8 @@ getTypeSpecifierLocation(const VarDecl *Var,
return TypeSpecifier;
}
std::optional<SourceRange> mergeReplacementRange(SourceRange &TypeSpecifier,
const Token &ConstToken) {
static std::optional<SourceRange>
mergeReplacementRange(SourceRange &TypeSpecifier, const Token &ConstToken) {
if (TypeSpecifier.getBegin().getLocWithOffset(-1) == ConstToken.getEndLoc()) {
TypeSpecifier.setBegin(ConstToken.getLocation());
return std::nullopt;
@ -86,21 +89,19 @@ std::optional<SourceRange> mergeReplacementRange(SourceRange &TypeSpecifier,
return SourceRange(ConstToken.getLocation(), ConstToken.getEndLoc());
}
bool isPointerConst(QualType QType) {
static bool isPointerConst(QualType QType) {
QualType Pointee = QType->getPointeeType();
assert(!Pointee.isNull() && "can't have a null Pointee");
return Pointee.isConstQualified();
}
bool isAutoPointerConst(QualType QType) {
static bool isAutoPointerConst(QualType QType) {
QualType Pointee =
cast<AutoType>(QType->getPointeeType().getTypePtr())->desugar();
assert(!Pointee.isNull() && "can't have a null Pointee");
return Pointee.isConstQualified();
}
} // namespace
QualifiedAutoCheck::QualifiedAutoCheck(StringRef Name,
ClangTidyContext *Context)
: ClangTidyCheck(Name, Context),

View File

@ -14,19 +14,18 @@ using namespace clang::ast_matchers;
namespace clang::tidy::readability {
namespace {
static const char *const RedundantReturnDiag =
"redundant return statement at the end "
"of a function with a void return type";
static const char *const RedundantContinueDiag =
"redundant continue statement at the "
"end of loop statement";
const char *const RedundantReturnDiag = "redundant return statement at the end "
"of a function with a void return type";
const char *const RedundantContinueDiag = "redundant continue statement at the "
"end of loop statement";
bool isLocationInMacroExpansion(const SourceManager &SM, SourceLocation Loc) {
static bool isLocationInMacroExpansion(const SourceManager &SM,
SourceLocation Loc) {
return SM.isMacroBodyExpansion(Loc) || SM.isMacroArgExpansion(Loc);
}
} // namespace
void RedundantControlFlowCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(
functionDecl(isDefinition(), returns(voidType()),

View File

@ -13,16 +13,14 @@
namespace clang::tidy::utils::type_traits {
namespace {
bool classHasTrivialCopyAndDestroy(QualType Type) {
static bool classHasTrivialCopyAndDestroy(QualType Type) {
auto *Record = Type->getAsCXXRecordDecl();
return Record && Record->hasDefinition() &&
!Record->hasNonTrivialCopyConstructor() &&
!Record->hasNonTrivialDestructor();
}
bool hasDeletedCopyConstructor(QualType Type) {
static bool hasDeletedCopyConstructor(QualType Type) {
auto *Record = Type->getAsCXXRecordDecl();
if (!Record || !Record->hasDefinition())
return false;
@ -33,8 +31,6 @@ bool hasDeletedCopyConstructor(QualType Type) {
return false;
}
} // namespace
std::optional<bool> isExpensiveToCopy(QualType Type,
const ASTContext &Context) {
if (Type->isDependentType() || Type->isIncompleteType())

View File

@ -215,7 +215,8 @@ Changes in existing checks
- Improved :doc:`readability-identifier-naming
<clang-tidy/checks/readability/identifier-naming>` check by ignoring
declarations in system headers.
declarations in system headers. The documentation is also improved to
differentiate the general options from the specific ones.
- Improved :doc:`readability-qualified-auto
<clang-tidy/checks/readability/qualified-auto>` check by adding the option

View File

@ -43,14 +43,21 @@ The options and their corresponding values are:
- ``LowerCase`` - example: ``int i_Variable``
- ``CamelCase`` - example: ``int IVariable``
Options
-------
Options summary
---------------
The following options are described below:
The available options are summarized below:
**General options**
- :option:`AbstractClassCase`, :option:`AbstractClassPrefix`, :option:`AbstractClassSuffix`, :option:`AbstractClassIgnoredRegexp`, :option:`AbstractClassHungarianPrefix`
- :option:`AggressiveDependentMemberLookup`
- :option:`CheckAnonFieldInParent`
- :option:`GetConfigPerFile`
- :option:`IgnoreMainLikeFunctions`
**Specific options**
- :option:`AbstractClassCase`, :option:`AbstractClassPrefix`, :option:`AbstractClassSuffix`, :option:`AbstractClassIgnoredRegexp`, :option:`AbstractClassHungarianPrefix`
- :option:`ClassCase`, :option:`ClassPrefix`, :option:`ClassSuffix`, :option:`ClassIgnoredRegexp`, :option:`ClassHungarianPrefix`
- :option:`ClassConstantCase`, :option:`ClassConstantPrefix`, :option:`ClassConstantSuffix`, :option:`ClassConstantIgnoredRegexp`, :option:`ClassConstantHungarianPrefix`
- :option:`ClassMemberCase`, :option:`ClassMemberPrefix`, :option:`ClassMemberSuffix`, :option:`ClassMemberIgnoredRegexp`, :option:`ClassMemberHungarianPrefix`
@ -66,13 +73,11 @@ The following options are described below:
- :option:`EnumCase`, :option:`EnumPrefix`, :option:`EnumSuffix`, :option:`EnumIgnoredRegexp`
- :option:`EnumConstantCase`, :option:`EnumConstantPrefix`, :option:`EnumConstantSuffix`, :option:`EnumConstantIgnoredRegexp`, :option:`EnumConstantHungarianPrefix`
- :option:`FunctionCase`, :option:`FunctionPrefix`, :option:`FunctionSuffix`, :option:`FunctionIgnoredRegexp`
- :option:`GetConfigPerFile`
- :option:`GlobalConstantCase`, :option:`GlobalConstantPrefix`, :option:`GlobalConstantSuffix`, :option:`GlobalConstantIgnoredRegexp`, :option:`GlobalConstantHungarianPrefix`
- :option:`GlobalConstantPointerCase`, :option:`GlobalConstantPointerPrefix`, :option:`GlobalConstantPointerSuffix`, :option:`GlobalConstantPointerIgnoredRegexp`, :option:`GlobalConstantPointerHungarianPrefix`
- :option:`GlobalFunctionCase`, :option:`GlobalFunctionPrefix`, :option:`GlobalFunctionSuffix`, :option:`GlobalFunctionIgnoredRegexp`
- :option:`GlobalPointerCase`, :option:`GlobalPointerPrefix`, :option:`GlobalPointerSuffix`, :option:`GlobalPointerIgnoredRegexp`, :option:`GlobalPointerHungarianPrefix`
- :option:`GlobalVariableCase`, :option:`GlobalVariablePrefix`, :option:`GlobalVariableSuffix`, :option:`GlobalVariableIgnoredRegexp`, :option:`GlobalVariableHungarianPrefix`
- :option:`IgnoreMainLikeFunctions`
- :option:`InlineNamespaceCase`, :option:`InlineNamespacePrefix`, :option:`InlineNamespaceSuffix`, :option:`InlineNamespaceIgnoredRegexp`
- :option:`LocalConstantCase`, :option:`LocalConstantPrefix`, :option:`LocalConstantSuffix`, :option:`LocalConstantIgnoredRegexp`, :option:`LocalConstantHungarianPrefix`
- :option:`LocalConstantPointerCase`, :option:`LocalConstantPointerPrefix`, :option:`LocalConstantPointerSuffix`, :option:`LocalConstantPointerIgnoredRegexp`, :option:`LocalConstantPointerHungarianPrefix`
@ -105,6 +110,12 @@ The following options are described below:
- :option:`VariableCase`, :option:`VariablePrefix`, :option:`VariableSuffix`, :option:`VariableIgnoredRegexp`, :option:`VariableHungarianPrefix`
- :option:`VirtualMethodCase`, :option:`VirtualMethodPrefix`, :option:`VirtualMethodSuffix`, :option:`VirtualMethodIgnoredRegexp`
Options description
-------------------
A detailed description of each option is presented below:
.. option:: AbstractClassCase
When defined, the check will ensure abstract class names conform to the

View File

@ -9,14 +9,14 @@ Introduction
============
Coroutines in C++ were introduced in C++20, and the user experience for
debugging them can still be challenging. This document guides you how to most
debugging them can still be challenging. This document guides you on how to most
efficiently debug coroutines and how to navigate existing shortcomings in
debuggers and compilers.
Coroutines are generally used either as generators or for asynchronous
programming. In this document, we will discuss both use cases. Even if you are
using coroutines for asynchronous programming, you should still read the
generators section, as it will introduce foundational debugging techniques also
generators section, as it introduces foundational debugging techniques also
applicable to the debugging of asynchronous programs.
Both compilers (clang, gcc, ...) and debuggers (lldb, gdb, ...) are
@ -34,15 +34,15 @@ scripting. This guide comes with a basic GDB script for coroutine debugging.
This guide will first showcase the more polished, bleeding-edge experience, but
will also show you how to debug coroutines with older toolchains. In general,
the older your toolchain, the deeper you will have to dive into the
implementation details of coroutines (such as their ABI). The further down in
this document you go, the more low-level, technical the content will become. If
implementation details of coroutines (such as their ABI). The further down you go in
this document, the more low-level, technical the content will become. If
you are on an up-to-date toolchain, you will hopefully be able to stop reading
earlier.
Debugging generators
====================
One of the two major use cases for coroutines in C++ are generators, i.e.,
One of the two major use cases for coroutines in C++ is generators, i.e.,
functions which can produce values via ``co_yield``. Values are produced
lazily, on-demand. For this purpose, every time a new value is requested, the
coroutine gets resumed. As soon as it reaches a ``co_yield`` and thereby
@ -141,7 +141,7 @@ a regular function.
Note the two additional variables ``__promise`` and ``__coro_frame``. Those
show the internal state of the coroutine. They are not relevant for our
generator example, but will be relevant for asynchronous programming described
generator example but will be relevant for asynchronous programming described
in the next section.
Stepping out of a coroutine
@ -174,7 +174,7 @@ Inspecting a suspended coroutine
--------------------------------
The ``print10Elements`` function receives an opaque ``generator`` type. Let's
assume we are suspended at the ``++gen;`` line, and want to inspect the
assume we are suspended at the ``++gen;`` line and want to inspect the
generator and its internal state.
To do so, we can simply look into the ``gen.hdl`` variable. LLDB comes with a
@ -188,7 +188,7 @@ We can see two function pointers ``resume`` and ``destroy``. These pointers
point to the resume / destroy functions. By inspecting those function pointers,
we can see that our ``generator`` is actually backed by our ``fibonacci``
coroutine. When using VS Code + lldb-dap, you can Cmd+Click on the function
address (``0x555...`` in the screenshot) to directly jump to the function
address (``0x555...`` in the screenshot) to jump directly to the function
definition backing your coroutine handle.
Next, we see the ``promise``. In our case, this reveals the current value of
@ -247,12 +247,12 @@ the line number of the current suspension point in the promise:
};
This stores the return address of ``await_suspend`` within the promise.
Thereby, we can read it back from the promise of a suspended coroutine, and map
Thereby, we can read it back from the promise of a suspended coroutine and map
it to an exact source code location. For a complete example, see the ``task``
type used below for asynchronous programming.
Alternatively, we can modify the C++ code to store the line number in the
promise type. We can use a ``std::source_location`` to get the line number of
promise type. We can use ``std::source_location`` to get the line number of
the await and store it inside the ``promise_type``. In the debugger, we can
then read the line number from the promise of the suspended coroutine.
@ -270,7 +270,7 @@ then read the line number from the promise of the suspended coroutine.
};
The downside of both approaches is that they come at the price of additional
runtime cost. In particular the second approach increases binary size, since it
runtime cost. In particular, the second approach increases binary size, since it
requires additional ``std::source_location`` objects, and those source
locations are not stripped by split-dwarf. Whether the first approach is worth
the additional runtime cost is a trade-off you need to make yourself.
@ -285,7 +285,7 @@ provide custom debugging support, so in addition to this guide, you might want
to check out their documentation.
When using coroutines for asynchronous programming, your library usually
provides you some ``task`` type. This type usually looks similar to this:
provides you with some ``task`` type. This type usually looks similar to this:
.. code-block:: c++
@ -479,7 +479,7 @@ One such solution is to store the list of in-flight coroutines in a collection:
};
With this in place, it is possible to inspect ``inflight_coroutines`` from the
debugger, and rely on LLDB's ``std::coroutine_handle`` pretty-printer to
debugger and rely on LLDB's ``std::coroutine_handle`` pretty-printer to
inspect the coroutines.
This technique will track *all* coroutines, also the ones which are currently
@ -498,8 +498,8 @@ LLDB before 21.0 did not yet show the ``__coro_frame`` inside
``coroutine_handle``. To inspect the coroutine frame, you had to use the
approach described in the :ref:`devirtualization` section.
LLDB before 18.0 was hiding the ``__promise`` and ``__coro_frame``
variable by default. The variables are still present, but they need to be
LLDB before 18.0 hid the ``__promise`` and ``__coro_frame``
variables by default. The variables are still present, but they need to be
explicitly added to the "watch" pane in VS Code or requested via
``print __promise`` and ``print __coro_frame`` from the debugger console.
@ -511,9 +511,9 @@ section.
Toolchain Implementation Details
================================
This section covers the ABI, as well as additional compiler-specific behavior.
This section covers the ABI as well as additional compiler-specific behavior.
The ABI is followed by all compilers, on all major systems, including Windows,
Linux and macOS. Different compilers emit different debug information, though.
Linux, and macOS. Different compilers emit different debug information, though.
Ramp, resume and destroy functions
----------------------------------
@ -595,7 +595,7 @@ functions as their first two members. As such, we can read the function
pointers from the coroutine frame and then obtain the function's name from its
address.
The promise is guaranteed to be at a 16 byte offset from the coroutine frame.
The promise is guaranteed to be at a 16-byte offset from the coroutine frame.
If we have a coroutine handle at address 0x416eb0, we can hence reinterpret-cast
the promise as follows:
@ -607,8 +607,8 @@ Implementation in clang / LLVM
------------------------------
The C++ Coroutines feature in the Clang compiler is implemented in two parts of
the compiler. Semantic analysis is performed in Clang, and Coroutine
construction and optimization takes place in the LLVM middle-end.
the compiler. Semantic analysis is performed in Clang, and coroutine
construction and optimization take place in the LLVM middle-end.
For each coroutine function, the frontend generates a single corresponding
LLVM-IR function. This function uses special ``llvm.coro.suspend`` intrinsics
@ -622,7 +622,7 @@ points into the coroutine frame. Most of the heavy lifting to preserve debugging
information is done in this pass. This pass needs to rewrite all variable
locations to point into the coroutine frame.
Afterwards, a couple of additional optimizations are applied, before code
Afterwards, a couple of additional optimizations are applied before code
gets emitted, but none of them are really interesting regarding debugging
information.
@ -636,8 +636,8 @@ However, this is not possible for coroutine frames because the frames are
constructed in the LLVM middle-end.
To mitigate this problem, the LLVM middle end attempts to generate some debug
information, which is unfortunately incomplete, since much of the language
specific information is missing in the middle end.
information, which is unfortunately incomplete, since much of the
language-specific information is missing in the middle end.
.. _devirtualization:
@ -655,7 +655,7 @@ There are two possible approaches to do so:
We can lookup their types and thereby get the types of promise
and coroutine frame.
In gdb, one can use the following approach to devirtualize coroutine type,
In gdb, one can use the following approach to devirtualize a coroutine type,
assuming we have a ``std::coroutine_handle`` is at address 0x418eb0:
::
@ -679,7 +679,7 @@ LLDB comes with devirtualization support out of the box, as part of the
pretty-printer for ``std::coroutine_handle``. Internally, this pretty-printer
uses the second approach. We look up the types in the destroy function and not
the resume function because the resume function pointer will be set to a
nullptr as soon as a coroutine reaches its final suspension point. If we used
``nullptr`` as soon as a coroutine reaches its final suspension point. If we used
the resume function, devirtualization would hence fail for all coroutines that
have reached their final suspension point.
@ -687,10 +687,10 @@ Interpreting the coroutine frame in optimized builds
----------------------------------------------------
The ``__coro_frame`` variable usually refers to the coroutine frame of an
*in-flight* coroutine. This means, the coroutine is currently executing.
*in-flight* coroutine. This means the coroutine is currently executing.
However, the compiler only guarantees the coroutine frame to be in a consistent
state while the coroutine is suspended. As such, the variables inside the
``__coro_frame`` variable might be outdated, in particular when optimizations
``__coro_frame`` variable might be outdated, particularly when optimizations
are enabled.
Furthermore, when optimizations are enabled, the compiler will layout the
@ -731,7 +731,7 @@ despite ``a`` being frequently incremented.
While this might be surprising, this is a result of the optimizer recognizing
that it can eliminate most of the load/store operations.
The above code gets optimized to the equivalent of:
The above code is optimized to the equivalent of:
.. code-block:: c++
@ -1180,5 +1180,5 @@ The authors of the Folly libraries wrote a blog post series on how they debug co
* `Async stack traces in folly: Improving debugging in the developer lifecycle <https://developers.facebook.com/blog/post/2021/10/21/async-stack-traces-folly-improving-debugging-developer-lifecycle/>`_
Besides some topics also covered here (stack traces from the debugger), Folly's blog post series also covers
more additional topics, such as capturing async stack traces in performance profiles via eBPF filters
additional topics, such as capturing async stack traces in performance profiles via eBPF filters
and printing async stack traces on crashes.

View File

@ -37,6 +37,22 @@ latest release, please see the `Clang Web Site <https://clang.llvm.org>`_ or the
Potentially Breaking Changes
============================
- Clang will now emit a warning if the auto-detected GCC installation
directory (i.e. the one with the largest version number) does not
contain libstdc++ include directories although a "complete" GCC
installation directory containing the include directories is
available. It is planned to change the auto-detection to prefer the
"complete" directory in the future. The warning will disappear if
the libstdc++ include directories are either installed or removed
for all GCC installation directories considered by the
auto-detection; see the output of ``clang -v`` for a list of those
directories. If the GCC installations cannot be modified and
maintaining the current choice of the auto-detection is desired, the
GCC installation directory can be selected explicitly using the
``--gcc-install-dir`` command line argument. This will silence the
warning. It can also be disabled using the
``-Wno-gcc-install-dir-libstdcxx`` command line flag.
C/C++ Language Potentially Breaking Changes
-------------------------------------------
@ -229,7 +245,7 @@ Bug Fixes in This Version
cast chain. (#GH149967).
- Fixed a crash with incompatible pointer to integer conversions in designated
initializers involving string literals. (#GH154046)
- Clang's ``<stddef.h>`` now properly declares ``nullptr_t`` in C++ mode. (#GH154577).
- Fixed scope of typedefs present inside a template class. (#GH91451)
Bug Fixes to Compiler Builtins
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -293,6 +309,13 @@ NVPTX Support
X86 Support
^^^^^^^^^^^
- More SSE, AVX and AVX512 intrinsics, including initializers and general
arithmetic can now be used in C++ constant expressions.
- Some SSE, AVX and AVX512 intrinsics have been converted to wrap
generic __builtin intrinsics.
- NOTE: Please avoid use of the __builtin_ia32_* intrinsics - these are not
guaranteed to exist in future releases, or match behaviour with previous
releases of clang or other compilers.
Arm and AArch64 Support
^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -23,20 +23,20 @@
#include "clang/Basic/DiagnosticInstallAPI.h"
#include "clang/Basic/DiagnosticLex.h"
#include "clang/Basic/DiagnosticParse.h"
#include "clang/Basic/DiagnosticRefactoring.h"
#include "clang/Basic/DiagnosticSema.h"
#include "clang/Basic/DiagnosticSerialization.h"
#include "clang/Basic/DiagnosticRefactoring.h"
namespace clang {
template <size_t SizeOfStr, typename FieldType>
class StringSizerHelper {
template <size_t SizeOfStr, typename FieldType> class StringSizerHelper {
static_assert(SizeOfStr <= FieldType(~0U), "Field too small!");
public:
enum { Size = SizeOfStr };
};
} // end namespace clang
#define STR_SIZE(str, fieldTy) clang::StringSizerHelper<sizeof(str)-1, \
fieldTy>::Size
#define STR_SIZE(str, fieldTy) \
clang::StringSizerHelper<sizeof(str) - 1, fieldTy>::Size
#endif

View File

@ -627,11 +627,23 @@ let Features = "avx2", Attributes = [NoThrow, Const, RequiredVectorWidth<256>] i
let Features = "avx2", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<256>] in {
def pmuldq256 : X86Builtin<"_Vector<4, long long int>(_Vector<8, int>, _Vector<8, int>)">;
def pmuludq256 : X86Builtin<"_Vector<4, long long int>(_Vector<8, int>, _Vector<8, int>)">;
}
let Features = "avx2", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<256>] in {
def pmulhuw256 : X86Builtin<"_Vector<16, unsigned short>(_Vector<16, unsigned short>, _Vector<16, unsigned short>)">;
def pmulhw256 : X86Builtin<"_Vector<16, short>(_Vector<16, short>, _Vector<16, short>)">;
def psllv8si : X86Builtin<"_Vector<8, int>(_Vector<8, int>, _Vector<8, int>)">;
def psrav8si : X86Builtin<"_Vector<8, int>(_Vector<8, int>, _Vector<8, int>)">;
def psrlv8si : X86Builtin<"_Vector<8, int>(_Vector<8, int>, _Vector<8, int>)">;
def psllv4di : X86Builtin<"_Vector<4, long long int>(_Vector<4, long long int>, _Vector<4, long long int>)">;
def psrlv4di : X86Builtin<"_Vector<4, long long int>(_Vector<4, long long int>, _Vector<4, long long int>)">;
}
let Features = "avx2", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<128>] in {
def psllv4si : X86Builtin<"_Vector<4, int>(_Vector<4, int>, _Vector<4, int>)">;
def psrav4si : X86Builtin<"_Vector<4, int>(_Vector<4, int>, _Vector<4, int>)">;
def psrlv4si : X86Builtin<"_Vector<4, int>(_Vector<4, int>, _Vector<4, int>)">;
def psllv2di : X86Builtin<"_Vector<2, long long int>(_Vector<2, long long int>, _Vector<2, long long int>)">;
def psrlv2di : X86Builtin<"_Vector<2, long long int>(_Vector<2, long long int>, _Vector<2, long long int>)">;
}
let Features = "avx2", Attributes = [NoThrow, RequiredVectorWidth<256>] in {
@ -654,46 +666,6 @@ let Features = "avx2", Attributes = [NoThrow, RequiredVectorWidth<128>] in {
def maskstoreq : X86Builtin<"void(_Vector<2, long long int *>, _Vector<2, long long int>, _Vector<2, long long int>)">;
}
let Features = "avx2", Attributes = [NoThrow, Const, RequiredVectorWidth<256>] in {
def psllv8si : X86Builtin<"_Vector<8, int>(_Vector<8, int>, _Vector<8, int>)">;
}
let Features = "avx2", Attributes = [NoThrow, Const, RequiredVectorWidth<128>] in {
def psllv4si : X86Builtin<"_Vector<4, int>(_Vector<4, int>, _Vector<4, int>)">;
}
let Features = "avx2", Attributes = [NoThrow, Const, RequiredVectorWidth<256>] in {
def psllv4di : X86Builtin<"_Vector<4, long long int>(_Vector<4, long long int>, _Vector<4, long long int>)">;
}
let Features = "avx2", Attributes = [NoThrow, Const, RequiredVectorWidth<128>] in {
def psllv2di : X86Builtin<"_Vector<2, long long int>(_Vector<2, long long int>, _Vector<2, long long int>)">;
}
let Features = "avx2", Attributes = [NoThrow, Const, RequiredVectorWidth<256>] in {
def psrav8si : X86Builtin<"_Vector<8, int>(_Vector<8, int>, _Vector<8, int>)">;
}
let Features = "avx2", Attributes = [NoThrow, Const, RequiredVectorWidth<128>] in {
def psrav4si : X86Builtin<"_Vector<4, int>(_Vector<4, int>, _Vector<4, int>)">;
}
let Features = "avx2", Attributes = [NoThrow, Const, RequiredVectorWidth<256>] in {
def psrlv8si : X86Builtin<"_Vector<8, int>(_Vector<8, int>, _Vector<8, int>)">;
}
let Features = "avx2", Attributes = [NoThrow, Const, RequiredVectorWidth<128>] in {
def psrlv4si : X86Builtin<"_Vector<4, int>(_Vector<4, int>, _Vector<4, int>)">;
}
let Features = "avx2", Attributes = [NoThrow, Const, RequiredVectorWidth<256>] in {
def psrlv4di : X86Builtin<"_Vector<4, long long int>(_Vector<4, long long int>, _Vector<4, long long int>)">;
}
let Features = "avx2", Attributes = [NoThrow, Const, RequiredVectorWidth<128>] in {
def psrlv2di : X86Builtin<"_Vector<2, long long int>(_Vector<2, long long int>, _Vector<2, long long int>)">;
}
let Features = "avx2", Attributes = [NoThrow, RequiredVectorWidth<128>] in {
def gatherd_pd : X86Builtin<"_Vector<2, double>(_Vector<2, double>, double const *, _Vector<4, int>, _Vector<2, double>, _Constant char)">;
}

View File

@ -885,4 +885,9 @@ def warn_drv_openacc_without_cir
: Warning<"OpenACC directives will result in no runtime behavior; use "
"-fclangir to enable runtime effect">,
InGroup<SourceUsesOpenACC>;
def warn_drv_gcc_install_dir_libstdcxx : Warning<
"future releases of the clang compiler will prefer GCC installations "
"containing libstdc++ include directories; '%0' would be chosen over '%1'">,
InGroup<DiagGroup<"gcc-install-dir-libstdcxx">>;
}

View File

@ -23,76 +23,78 @@
#include <vector>
namespace clang {
class DiagnosticsEngine;
class DiagnosticBuilder;
class LangOptions;
class SourceLocation;
class DiagnosticsEngine;
class DiagnosticBuilder;
class LangOptions;
class SourceLocation;
// Import the diagnostic enums themselves.
namespace diag {
enum class Group;
// Import the diagnostic enums themselves.
namespace diag {
enum class Group;
// Size of each of the diagnostic categories.
enum {
DIAG_SIZE_COMMON = 300,
DIAG_SIZE_DRIVER = 400,
DIAG_SIZE_FRONTEND = 200,
DIAG_SIZE_SERIALIZATION = 120,
DIAG_SIZE_LEX = 500,
DIAG_SIZE_PARSE = 800,
DIAG_SIZE_AST = 300,
DIAG_SIZE_COMMENT = 100,
DIAG_SIZE_CROSSTU = 100,
DIAG_SIZE_SEMA = 5000,
DIAG_SIZE_ANALYSIS = 100,
DIAG_SIZE_REFACTORING = 1000,
DIAG_SIZE_INSTALLAPI = 100,
};
// Start position for diagnostics.
enum {
DIAG_START_COMMON = 0,
DIAG_START_DRIVER = DIAG_START_COMMON + static_cast<int>(DIAG_SIZE_COMMON),
DIAG_START_FRONTEND = DIAG_START_DRIVER + static_cast<int>(DIAG_SIZE_DRIVER),
DIAG_START_SERIALIZATION = DIAG_START_FRONTEND + static_cast<int>(DIAG_SIZE_FRONTEND),
DIAG_START_LEX = DIAG_START_SERIALIZATION + static_cast<int>(DIAG_SIZE_SERIALIZATION),
DIAG_START_PARSE = DIAG_START_LEX + static_cast<int>(DIAG_SIZE_LEX),
DIAG_START_AST = DIAG_START_PARSE + static_cast<int>(DIAG_SIZE_PARSE),
DIAG_START_COMMENT = DIAG_START_AST + static_cast<int>(DIAG_SIZE_AST),
DIAG_START_CROSSTU = DIAG_START_COMMENT + static_cast<int>(DIAG_SIZE_COMMENT),
DIAG_START_SEMA = DIAG_START_CROSSTU + static_cast<int>(DIAG_SIZE_CROSSTU),
DIAG_START_ANALYSIS = DIAG_START_SEMA + static_cast<int>(DIAG_SIZE_SEMA),
DIAG_START_REFACTORING = DIAG_START_ANALYSIS + static_cast<int>(DIAG_SIZE_ANALYSIS),
DIAG_START_INSTALLAPI = DIAG_START_REFACTORING + static_cast<int>(DIAG_SIZE_REFACTORING),
DIAG_UPPER_LIMIT = DIAG_START_INSTALLAPI + static_cast<int>(DIAG_SIZE_INSTALLAPI)
};
// Size of each of the diagnostic categories.
enum {
DIAG_SIZE_COMMON = 300,
DIAG_SIZE_DRIVER = 400,
DIAG_SIZE_FRONTEND = 200,
DIAG_SIZE_SERIALIZATION = 120,
DIAG_SIZE_LEX = 500,
DIAG_SIZE_PARSE = 800,
DIAG_SIZE_AST = 300,
DIAG_SIZE_COMMENT = 100,
DIAG_SIZE_CROSSTU = 100,
DIAG_SIZE_SEMA = 5000,
DIAG_SIZE_ANALYSIS = 100,
DIAG_SIZE_REFACTORING = 1000,
DIAG_SIZE_INSTALLAPI = 100,
};
// Start position for diagnostics.
// clang-format off
enum {
DIAG_START_COMMON = 0,
DIAG_START_DRIVER = DIAG_START_COMMON + static_cast<int>(DIAG_SIZE_COMMON),
DIAG_START_FRONTEND = DIAG_START_DRIVER + static_cast<int>(DIAG_SIZE_DRIVER),
DIAG_START_SERIALIZATION = DIAG_START_FRONTEND + static_cast<int>(DIAG_SIZE_FRONTEND),
DIAG_START_LEX = DIAG_START_SERIALIZATION + static_cast<int>(DIAG_SIZE_SERIALIZATION),
DIAG_START_PARSE = DIAG_START_LEX + static_cast<int>(DIAG_SIZE_LEX),
DIAG_START_AST = DIAG_START_PARSE + static_cast<int>(DIAG_SIZE_PARSE),
DIAG_START_COMMENT = DIAG_START_AST + static_cast<int>(DIAG_SIZE_AST),
DIAG_START_CROSSTU = DIAG_START_COMMENT + static_cast<int>(DIAG_SIZE_COMMENT),
DIAG_START_SEMA = DIAG_START_CROSSTU + static_cast<int>(DIAG_SIZE_CROSSTU),
DIAG_START_ANALYSIS = DIAG_START_SEMA + static_cast<int>(DIAG_SIZE_SEMA),
DIAG_START_REFACTORING = DIAG_START_ANALYSIS + static_cast<int>(DIAG_SIZE_ANALYSIS),
DIAG_START_INSTALLAPI = DIAG_START_REFACTORING + static_cast<int>(DIAG_SIZE_REFACTORING),
DIAG_UPPER_LIMIT = DIAG_START_INSTALLAPI + static_cast<int>(DIAG_SIZE_INSTALLAPI)
};
// clang-format on
class CustomDiagInfo;
class CustomDiagInfo;
/// All of the diagnostics that can be emitted by the frontend.
typedef unsigned kind;
/// All of the diagnostics that can be emitted by the frontend.
typedef unsigned kind;
/// Enum values that allow the client to map NOTEs, WARNINGs, and EXTENSIONs
/// to either Ignore (nothing), Remark (emit a remark), Warning
/// (emit a warning) or Error (emit as an error). It allows clients to
/// map ERRORs to Error or Fatal (stop emitting diagnostics after this one).
enum class Severity : uint8_t {
// NOTE: 0 means "uncomputed".
Ignored = 1, ///< Do not present this diagnostic, ignore it.
Remark = 2, ///< Present this diagnostic as a remark.
Warning = 3, ///< Present this diagnostic as a warning.
Error = 4, ///< Present this diagnostic as an error.
Fatal = 5 ///< Present this diagnostic as a fatal error.
};
/// Enum values that allow the client to map NOTEs, WARNINGs, and EXTENSIONs
/// to either Ignore (nothing), Remark (emit a remark), Warning
/// (emit a warning) or Error (emit as an error). It allows clients to
/// map ERRORs to Error or Fatal (stop emitting diagnostics after this one).
enum class Severity : uint8_t {
// NOTE: 0 means "uncomputed".
Ignored = 1, ///< Do not present this diagnostic, ignore it.
Remark = 2, ///< Present this diagnostic as a remark.
Warning = 3, ///< Present this diagnostic as a warning.
Error = 4, ///< Present this diagnostic as an error.
Fatal = 5 ///< Present this diagnostic as a fatal error.
};
/// Flavors of diagnostics we can emit. Used to filter for a particular
/// kind of diagnostic (for instance, for -W/-R flags).
enum class Flavor {
WarningOrError, ///< A diagnostic that indicates a problem or potential
///< problem. Can be made fatal by -Werror.
Remark ///< A diagnostic that indicates normal progress through
///< compilation.
};
} // end namespace diag
/// Flavors of diagnostics we can emit. Used to filter for a particular
/// kind of diagnostic (for instance, for -W/-R flags).
enum class Flavor {
WarningOrError, ///< A diagnostic that indicates a problem or potential
///< problem. Can be made fatal by -Werror.
Remark ///< A diagnostic that indicates normal progress through
///< compilation.
};
} // end namespace diag
} // end namespace clang
// This has to be included *after* the DIAG_START_ enums above are defined.
@ -173,7 +175,8 @@ public:
/// Used for handling and querying diagnostic IDs.
///
/// Can be used and shared by multiple Diagnostics for multiple translation units.
/// Can be used and shared by multiple Diagnostics for multiple translation
/// units.
class DiagnosticIDs : public RefCountedBase<DiagnosticIDs> {
public:
/// The level of the diagnostic, after it has been through mapping.
@ -498,6 +501,6 @@ private:
friend class DiagnosticsEngine;
};
} // end namespace clang
} // end namespace clang
#endif

View File

@ -50,6 +50,45 @@ class CIR_UnitAttr<string name, string attrMnemonic, list<Trait> traits = []>
let isOptional = 1;
}
//===----------------------------------------------------------------------===//
// SourceLanguageAttr
//===----------------------------------------------------------------------===//
// TODO: Add cases for other languages that Clang supports.
def CIR_SourceLanguage : CIR_I32EnumAttr<"SourceLanguage", "source language", [
I32EnumAttrCase<"C", 1, "c">,
I32EnumAttrCase<"CXX", 2, "cxx">
]> {
// The enum attr class is defined in `CIR_SourceLanguageAttr` below,
// so that it can define extra class methods.
let genSpecializedAttr = 0;
}
def CIR_SourceLanguageAttr : CIR_EnumAttr<CIR_SourceLanguage, "lang"> {
let summary = "Module source language";
let description = [{
Represents the source language used to generate the module.
Example:
```
// Module compiled from C.
module attributes {cir.lang = cir.lang<c>} {}
// Module compiled from C++.
module attributes {cir.lang = cir.lang<cxx>} {}
```
Module source language attribute name is `cir.lang` is defined by
`getSourceLanguageAttrName` method in CIRDialect class.
}];
let extraClassDeclaration = [{
bool isC() const { return getValue() == SourceLanguage::C; }
bool isCXX() const { return getValue() == SourceLanguage::CXX; }
}];
}
//===----------------------------------------------------------------------===//
// OptInfoAttr
//===----------------------------------------------------------------------===//
@ -496,6 +535,72 @@ def CIR_GlobalViewAttr : CIR_Attr<"GlobalView", "global_view", [
}];
}
//===----------------------------------------------------------------------===//
// VTableAttr
//===----------------------------------------------------------------------===//
def CIR_VTableAttr : CIR_Attr<"VTable", "vtable", [TypedAttrInterface]> {
let summary = "Represents a C++ vtable";
let description = [{
Wraps a #cir.const_record containing one or more vtable arrays.
In most cases, the anonymous record type wrapped by this attribute will
contain a single array corresponding to the vtable for one class. However,
in the case of multiple inheritence, the anonymous structure may contain
multiple arrays, each of which is a vtable.
Example 1 (single vtable):
```mlir
cir.global linkonce_odr @_ZTV6Mother =
#cir.vtable<{
#cir.const_array<[
#cir.ptr<null> : !cir.ptr<!u8i>,
#cir.global_view<@_ZTI6Mother> : !cir.ptr<!u8i>,
#cir.global_view<@_ZN6Mother9MotherFooEv> : !cir.ptr<!u8i>,
#cir.global_view<@_ZN6Mother10MotherFoo2Ev> : !cir.ptr<!u8i>
]> : !cir.array<!cir.ptr<!u8i> x 4>
}> : !rec_anon_struct1
```
Example 2 (multiple vtables):
```mlir
cir.global linkonce_odr @_ZTV5Child =
#cir.vtable<{
#cir.const_array<[
#cir.ptr<null> : !cir.ptr<!u8i>,
#cir.global_view<@_ZTI5Child> : !cir.ptr<!u8i>,
#cir.global_view<@_ZN5Child9MotherFooEv> : !cir.ptr<!u8i>,
#cir.global_view<@_ZN6Mother10MotherFoo2Ev> : !cir.ptr<!u8i>
]> : !cir.array<!cir.ptr<!u8i> x 4>,
#cir.const_array<[
#cir.ptr<-8 : i64> : !cir.ptr<!u8i>,
#cir.global_view<@_ZTI5Child> : !cir.ptr<!u8i>,
#cir.global_view<@_ZN6Father9FatherFooEv> : !cir.ptr<!u8i>
]> : !cir.array<!cir.ptr<!u8i> x 3>
}> : !rec_anon_struct2
```
}];
// `data` is a const record with one element, containing an array of
// vtable information.
let parameters = (ins
AttributeSelfTypeParameter<"">:$type,
"mlir::ArrayAttr":$data
);
let builders = [
AttrBuilderWithInferredContext<(ins "mlir::Type":$type,
"mlir::ArrayAttr":$data), [{
return $_get(type.getContext(), type, data);
}]>
];
let genVerifyDecl = 1;
let assemblyFormat = [{
`<` custom<RecordMembers>($data) `>`
}];
}
//===----------------------------------------------------------------------===//
// ConstComplexAttr
//===----------------------------------------------------------------------===//

View File

@ -35,6 +35,7 @@ def CIR_Dialect : Dialect {
let hasConstantMaterializer = 1;
let extraClassDeclaration = [{
static llvm::StringRef getSourceLanguageAttrName() { return "cir.lang"; }
static llvm::StringRef getTripleAttrName() { return "cir.triple"; }
static llvm::StringRef getOptInfoAttrName() { return "cir.opt_info"; }
static llvm::StringRef getCalleeAttrName() { return "callee"; }

View File

@ -26,6 +26,7 @@ std::unique_ptr<Pass> createCIRSimplifyPass();
std::unique_ptr<Pass> createHoistAllocasPass();
std::unique_ptr<Pass> createLoweringPreparePass();
std::unique_ptr<Pass> createLoweringPreparePass(clang::ASTContext *astCtx);
std::unique_ptr<Pass> createGotoSolverPass();
void populateCIRPreLoweringPasses(mlir::OpPassManager &pm);

View File

@ -72,6 +72,16 @@ def CIRFlattenCFG : Pass<"cir-flatten-cfg"> {
let dependentDialects = ["cir::CIRDialect"];
}
def GotoSolver : Pass<"cir-goto-solver"> {
let summary = "Replaces goto operations with branches";
let description = [{
This pass transforms CIR and replaces goto-s with branch
operations to the proper blocks.
}];
let constructor = "mlir::createGotoSolverPass()";
let dependentDialects = ["cir::CIRDialect"];
}
def LoweringPrepare : Pass<"cir-lowering-prepare"> {
let summary = "Lower to more fine-grained CIR operations before lowering to "
"other dialects";

View File

@ -264,6 +264,7 @@ struct MissingFeatures {
static bool setNonGC() { return false; }
static bool setObjCGCLValueClass() { return false; }
static bool setTargetAttributes() { return false; }
static bool sourceLanguageCases() { return false; }
static bool stackBase() { return false; }
static bool stackSaveOp() { return false; }
static bool targetCIRGenInfoArch() { return false; }

View File

@ -32,6 +32,7 @@
namespace llvm {
class AttrBuilder;
class Constant;
class ConstantInt;
class Function;
class FunctionType;
class Type;
@ -126,6 +127,12 @@ uint16_t getPointerAuthDeclDiscriminator(CodeGenModule &CGM, GlobalDecl GD);
uint16_t getPointerAuthTypeDiscriminator(CodeGenModule &CGM,
QualType FunctionType);
/// Return a signed constant pointer.
llvm::Constant *getConstantSignedPointer(CodeGenModule &CGM,
llvm::Constant *Pointer, unsigned Key,
llvm::Constant *StorageAddress,
llvm::ConstantInt *OtherDiscriminator);
/// Given the language and code-generation options that Clang was configured
/// with, set the default LLVM IR attributes for a function definition.
/// The attributes set here are mostly global target-configuration and

View File

@ -9468,8 +9468,12 @@ def fspv_target_env_EQ : Joined<["-"], "fspv-target-env=">, Group<dxc_Group>,
def fspv_extension_EQ
: Joined<["-"], "fspv-extension=">,
Group<dxc_Group>,
HelpText<"Specify the available SPIR-V extensions. If this option is not "
"specified, then all extensions are available.">;
HelpText<
"Specify the available SPIR-V extensions. If this option is not "
"specified, then all extensions are available. If KHR is specified, "
"then all KHR extensions will be available. If DXC is specifided, "
"then all extensions implemented by the DirectX Shader compiler will "
"be available. This option is useful for moving from DXC to Clang.">;
def fvk_use_dx_layout
: DXCFlag<"fvk-use-dx-layout">,
HelpText<"Use DirectX memory layout for Vulkan resources.">;

View File

@ -224,9 +224,6 @@ protected:
static void addSystemFrameworkInclude(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args,
const Twine &Path);
static void addSystemInclude(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args,
const Twine &Path);
static void addExternCSystemInclude(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args,
const Twine &Path);
@ -246,6 +243,9 @@ protected:
///@}
public:
static void addSystemInclude(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args,
const Twine &Path);
virtual ~ToolChain();
// Accessors

View File

@ -205,6 +205,8 @@ static bool interp__builtin_strcmp(InterpState &S, CodePtr OpPC,
if (A.isDummy() || B.isDummy())
return false;
if (!A.isBlockPointer() || !B.isBlockPointer())
return false;
bool IsWide = ID == Builtin::BIwcscmp || ID == Builtin::BIwcsncmp ||
ID == Builtin::BI__builtin_wcscmp ||
@ -212,7 +214,10 @@ static bool interp__builtin_strcmp(InterpState &S, CodePtr OpPC,
assert(A.getFieldDesc()->isPrimitiveArray());
assert(B.getFieldDesc()->isPrimitiveArray());
assert(getElemType(A).getTypePtr() == getElemType(B).getTypePtr());
// Different element types shouldn't happen, but with casts they can.
if (!S.getASTContext().hasSameUnqualifiedType(getElemType(A), getElemType(B)))
return false;
PrimType ElemT = *S.getContext().classify(getElemType(A));
auto returnResult = [&](int V) -> bool {
@ -2778,6 +2783,40 @@ static bool interp__builtin_elementwise_fma(InterpState &S, CodePtr OpPC,
return true;
}
/// AVX512 predicated move: "Result = Mask[] ? LHS[] : RHS[]".
static bool interp__builtin_select(InterpState &S, CodePtr OpPC,
const CallExpr *Call) {
const Pointer &RHS = S.Stk.pop<Pointer>();
const Pointer &LHS = S.Stk.pop<Pointer>();
PrimType MaskT = *S.getContext().classify(Call->getArg(0));
APSInt Mask = popToAPSInt(S.Stk, MaskT);
const Pointer &Dst = S.Stk.peek<Pointer>();
assert(LHS.getNumElems() == RHS.getNumElems());
assert(LHS.getNumElems() == Dst.getNumElems());
unsigned NumElems = LHS.getNumElems();
PrimType ElemT = LHS.getFieldDesc()->getPrimType();
PrimType DstElemT = Dst.getFieldDesc()->getPrimType();
for (unsigned I = 0; I != NumElems; ++I) {
if (ElemT == PT_Float) {
assert(DstElemT == PT_Float);
Dst.elem<Floating>(I) =
Mask[I] ? LHS.elem<Floating>(I) : RHS.elem<Floating>(I);
} else {
APSInt Elem;
INT_TYPE_SWITCH(ElemT, {
Elem = Mask[I] ? LHS.elem<T>(I).toAPSInt() : RHS.elem<T>(I).toAPSInt();
});
INT_TYPE_SWITCH_NO_BOOL(DstElemT,
{ Dst.elem<T>(I) = static_cast<T>(Elem); });
}
}
Dst.initializeAllElements();
return true;
}
bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
uint32_t BuiltinID) {
if (!S.getASTContext().BuiltinInfo.isConstantEvaluated(BuiltinID))
@ -3210,9 +3249,36 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
case clang::X86::BI__builtin_ia32_pmuludq256:
case clang::X86::BI__builtin_ia32_pmuludq512:
return interp__builtin_ia32_pmul(S, OpPC, Call, BuiltinID);
case Builtin::BI__builtin_elementwise_fma:
return interp__builtin_elementwise_fma(S, OpPC, Call);
case X86::BI__builtin_ia32_selectb_128:
case X86::BI__builtin_ia32_selectb_256:
case X86::BI__builtin_ia32_selectb_512:
case X86::BI__builtin_ia32_selectw_128:
case X86::BI__builtin_ia32_selectw_256:
case X86::BI__builtin_ia32_selectw_512:
case X86::BI__builtin_ia32_selectd_128:
case X86::BI__builtin_ia32_selectd_256:
case X86::BI__builtin_ia32_selectd_512:
case X86::BI__builtin_ia32_selectq_128:
case X86::BI__builtin_ia32_selectq_256:
case X86::BI__builtin_ia32_selectq_512:
case X86::BI__builtin_ia32_selectph_128:
case X86::BI__builtin_ia32_selectph_256:
case X86::BI__builtin_ia32_selectph_512:
case X86::BI__builtin_ia32_selectpbf_128:
case X86::BI__builtin_ia32_selectpbf_256:
case X86::BI__builtin_ia32_selectpbf_512:
case X86::BI__builtin_ia32_selectps_128:
case X86::BI__builtin_ia32_selectps_256:
case X86::BI__builtin_ia32_selectps_512:
case X86::BI__builtin_ia32_selectpd_128:
case X86::BI__builtin_ia32_selectpd_256:
case X86::BI__builtin_ia32_selectpd_512:
return interp__builtin_select(S, OpPC, Call);
default:
S.FFDiag(S.Current->getLocation(OpPC),
diag::note_invalid_subexpr_in_const_expr)

View File

@ -341,6 +341,8 @@ public:
QualType getType() const {
if (isTypeidPointer())
return QualType(Typeid.TypeInfoType, 0);
if (isFunctionPointer())
return asFunctionPointer().getFunction()->getDecl()->getType();
if (inPrimitiveArray() && Offset != asBlockPointer().Base) {
// Unfortunately, complex and vector types are not array types in clang,

View File

@ -11669,13 +11669,24 @@ bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) {
case clang::X86::BI__builtin_ia32_pmulhuw512:
case clang::X86::BI__builtin_ia32_pmulhw128:
case clang::X86::BI__builtin_ia32_pmulhw256:
case clang::X86::BI__builtin_ia32_pmulhw512: {
case clang::X86::BI__builtin_ia32_pmulhw512:
case clang::X86::BI__builtin_ia32_psllv2di:
case clang::X86::BI__builtin_ia32_psllv4di:
case clang::X86::BI__builtin_ia32_psllv4si:
case clang::X86::BI__builtin_ia32_psllv8si:
case clang::X86::BI__builtin_ia32_psrav4si:
case clang::X86::BI__builtin_ia32_psrav8si:
case clang::X86::BI__builtin_ia32_psrlv2di:
case clang::X86::BI__builtin_ia32_psrlv4di:
case clang::X86::BI__builtin_ia32_psrlv4si:
case clang::X86::BI__builtin_ia32_psrlv8si:{
APValue SourceLHS, SourceRHS;
if (!EvaluateAsRValue(Info, E->getArg(0), SourceLHS) ||
!EvaluateAsRValue(Info, E->getArg(1), SourceRHS))
return false;
QualType DestEltTy = E->getType()->castAs<VectorType>()->getElementType();
bool DestUnsigned = DestEltTy->isUnsignedIntegerOrEnumerationType();
unsigned SourceLen = SourceLHS.getVectorLength();
SmallVector<APValue, 4> ResultElements;
ResultElements.reserve(SourceLen);
@ -11687,12 +11698,12 @@ bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) {
case Builtin::BI__builtin_elementwise_add_sat:
ResultElements.push_back(APValue(
APSInt(LHS.isSigned() ? LHS.sadd_sat(RHS) : LHS.uadd_sat(RHS),
DestEltTy->isUnsignedIntegerOrEnumerationType())));
DestUnsigned)));
break;
case Builtin::BI__builtin_elementwise_sub_sat:
ResultElements.push_back(APValue(
APSInt(LHS.isSigned() ? LHS.ssub_sat(RHS) : LHS.usub_sat(RHS),
DestEltTy->isUnsignedIntegerOrEnumerationType())));
DestUnsigned)));
break;
case clang::X86::BI__builtin_ia32_pmulhuw128:
case clang::X86::BI__builtin_ia32_pmulhuw256:
@ -11706,6 +11717,40 @@ bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) {
ResultElements.push_back(APValue(APSInt(llvm::APIntOps::mulhs(LHS, RHS),
/*isUnsigned=*/false)));
break;
case clang::X86::BI__builtin_ia32_psllv2di:
case clang::X86::BI__builtin_ia32_psllv4di:
case clang::X86::BI__builtin_ia32_psllv4si:
case clang::X86::BI__builtin_ia32_psllv8si:
if (RHS.uge(RHS.getBitWidth())) {
ResultElements.push_back(
APValue(APSInt(APInt::getZero(RHS.getBitWidth()), DestUnsigned)));
break;
}
ResultElements.push_back(
APValue(APSInt(LHS.shl(RHS.getZExtValue()), DestUnsigned)));
break;
case clang::X86::BI__builtin_ia32_psrav4si:
case clang::X86::BI__builtin_ia32_psrav8si:
if (RHS.uge(RHS.getBitWidth())) {
ResultElements.push_back(
APValue(APSInt(LHS.ashr(RHS.getBitWidth() - 1), DestUnsigned)));
break;
}
ResultElements.push_back(
APValue(APSInt(LHS.ashr(RHS.getZExtValue()), DestUnsigned)));
break;
case clang::X86::BI__builtin_ia32_psrlv2di:
case clang::X86::BI__builtin_ia32_psrlv4di:
case clang::X86::BI__builtin_ia32_psrlv4si:
case clang::X86::BI__builtin_ia32_psrlv8si:
if (RHS.uge(RHS.getBitWidth())) {
ResultElements.push_back(
APValue(APSInt(APInt::getZero(RHS.getBitWidth()), DestUnsigned)));
break;
}
ResultElements.push_back(
APValue(APSInt(LHS.lshr(RHS.getZExtValue()), DestUnsigned)));
break;
}
}

View File

@ -174,6 +174,9 @@ protected:
DefineStd(Builder, "unix", Opts);
if (this->HasFloat128)
Builder.defineMacro("__FLOAT128__");
if (Opts.C11)
Builder.defineMacro("__STDC_NO_THREADS__");
}
public:

View File

@ -73,21 +73,54 @@ Address CIRGenFunction::emitPointerWithAlignment(const Expr *expr,
// Casts:
if (auto const *ce = dyn_cast<CastExpr>(expr)) {
if (isa<ExplicitCastExpr>(ce)) {
cgm.errorNYI(expr->getSourceRange(),
"emitPointerWithAlignment: explicit cast");
return Address::invalid();
}
if (const auto *ece = dyn_cast<ExplicitCastExpr>(ce))
cgm.emitExplicitCastExprType(ece);
switch (ce->getCastKind()) {
// Non-converting casts (but not C's implicit conversion from void*).
case CK_BitCast:
case CK_NoOp:
case CK_AddressSpaceConversion: {
cgm.errorNYI(expr->getSourceRange(),
"emitPointerWithAlignment: noop cast");
return Address::invalid();
} break;
if (const auto *ptrTy =
ce->getSubExpr()->getType()->getAs<PointerType>()) {
if (ptrTy->getPointeeType()->isVoidType())
break;
LValueBaseInfo innerBaseInfo;
assert(!cir::MissingFeatures::opTBAA());
Address addr =
emitPointerWithAlignment(ce->getSubExpr(), &innerBaseInfo);
if (baseInfo)
*baseInfo = innerBaseInfo;
if (isa<ExplicitCastExpr>(ce)) {
LValueBaseInfo targetTypeBaseInfo;
const QualType pointeeType = expr->getType()->getPointeeType();
const CharUnits align =
cgm.getNaturalTypeAlignment(pointeeType, &targetTypeBaseInfo);
// If the source l-value is opaque, honor the alignment of the
// casted-to type.
if (innerBaseInfo.getAlignmentSource() != AlignmentSource::Decl) {
if (baseInfo)
baseInfo->mergeForCast(targetTypeBaseInfo);
addr = Address(addr.getPointer(), addr.getElementType(), align);
}
}
assert(!cir::MissingFeatures::sanitizers());
const mlir::Type eltTy =
convertTypeForMem(expr->getType()->getPointeeType());
addr = getBuilder().createElementBitCast(getLoc(expr->getSourceRange()),
addr, eltTy);
assert(!cir::MissingFeatures::addressSpace());
return addr;
}
break;
}
// Array-to-pointer decay. TODO(cir): BaseInfo and TBAAInfo.
case CK_ArrayToPointerDecay:
@ -551,6 +584,37 @@ RValue CIRGenFunction::emitLoadOfLValue(LValue lv, SourceLocation loc) {
return RValue::get(nullptr);
}
static cir::FuncOp emitFunctionDeclPointer(CIRGenModule &cgm, GlobalDecl gd) {
assert(!cir::MissingFeatures::weakRefReference());
return cgm.getAddrOfFunction(gd);
}
static LValue emitFunctionDeclLValue(CIRGenFunction &cgf, const Expr *e,
GlobalDecl gd) {
const FunctionDecl *fd = cast<FunctionDecl>(gd.getDecl());
cir::FuncOp funcOp = emitFunctionDeclPointer(cgf.cgm, gd);
mlir::Location loc = cgf.getLoc(e->getSourceRange());
CharUnits align = cgf.getContext().getDeclAlign(fd);
assert(!cir::MissingFeatures::sanitizers());
mlir::Type fnTy = funcOp.getFunctionType();
mlir::Type ptrTy = cir::PointerType::get(fnTy);
mlir::Value addr = cgf.getBuilder().create<cir::GetGlobalOp>(
loc, ptrTy, funcOp.getSymName());
if (funcOp.getFunctionType() != cgf.convertType(fd->getType())) {
fnTy = cgf.convertType(fd->getType());
ptrTy = cir::PointerType::get(fnTy);
addr = cir::CastOp::create(cgf.getBuilder(), addr.getLoc(), ptrTy,
cir::CastKind::bitcast, addr);
}
return cgf.makeAddrLValue(Address(addr, fnTy, align), e->getType(),
AlignmentSource::Decl);
}
LValue CIRGenFunction::emitDeclRefLValue(const DeclRefExpr *e) {
const NamedDecl *nd = e->getDecl();
QualType ty = e->getType();
@ -607,6 +671,16 @@ LValue CIRGenFunction::emitDeclRefLValue(const DeclRefExpr *e) {
return emitLValue(bd->getBinding());
}
if (const auto *fd = dyn_cast<FunctionDecl>(nd)) {
LValue lv = emitFunctionDeclLValue(*this, e, fd);
// Emit debuginfo for the function declaration if the target wants to.
if (getContext().getTargetInfo().allowDebugInfoForExternalRef())
assert(!cir::MissingFeatures::generateDebugInfo());
return lv;
}
cgm.errorNYI(e->getSourceRange(), "emitDeclRefLValue: unhandled decl type");
return LValue();
}
@ -1401,11 +1475,6 @@ RValue CIRGenFunction::emitAnyExpr(const Expr *e, AggValueSlot aggSlot) {
llvm_unreachable("bad evaluation kind");
}
static cir::FuncOp emitFunctionDeclPointer(CIRGenModule &cgm, GlobalDecl gd) {
assert(!cir::MissingFeatures::weakRefReference());
return cgm.getAddrOfFunction(gd);
}
// Detect the unusual situation where an inline version is shadowed by a
// non-inline version. In that case we should pick the external one
// everywhere. That's GCC behavior too.

View File

@ -1905,6 +1905,8 @@ mlir::Value ScalarExprEmitter::VisitCastExpr(CastExpr *ce) {
cgf.getLoc(subExpr->getSourceRange()), cgf.convertType(destTy),
Visit(subExpr));
}
case CK_FunctionToPointerDecay:
return cgf.emitLValue(subExpr).getPointer();
default:
cgf.getCIRGenModule().errorNYI(subExpr->getSourceRange(),

View File

@ -103,6 +103,9 @@ CIRGenModule::CIRGenModule(mlir::MLIRContext &mlirContext,
PtrDiffTy =
cir::IntType::get(&getMLIRContext(), sizeTypeSize, /*isSigned=*/true);
theModule->setAttr(
cir::CIRDialect::getSourceLanguageAttrName(),
cir::SourceLanguageAttr::get(&mlirContext, getCIRSourceLanguage()));
theModule->setAttr(cir::CIRDialect::getTripleAttrName(),
builder.getStringAttr(getTriple().str()));
@ -510,6 +513,23 @@ void CIRGenModule::setNonAliasAttributes(GlobalDecl gd, mlir::Operation *op) {
assert(!cir::MissingFeatures::setTargetAttributes());
}
cir::SourceLanguage CIRGenModule::getCIRSourceLanguage() const {
using ClangStd = clang::LangStandard;
using CIRLang = cir::SourceLanguage;
auto opts = getLangOpts();
if (opts.CPlusPlus)
return CIRLang::CXX;
if (opts.C99 || opts.C11 || opts.C17 || opts.C23 || opts.C2y ||
opts.LangStd == ClangStd::lang_c89 ||
opts.LangStd == ClangStd::lang_gnu89)
return CIRLang::C;
// TODO(cir): support remaining source languages.
assert(!cir::MissingFeatures::sourceLanguageCases());
errorNYI("CIR does not yet support the given source language");
}
static void setLinkageForGV(cir::GlobalOp &gv, const NamedDecl *nd) {
// Set linkage and visibility in case we never see a definition.
LinkageInfo lv = nd->getLinkageAndVisibility();

View File

@ -461,6 +461,9 @@ private:
void replacePointerTypeArgs(cir::FuncOp oldF, cir::FuncOp newF);
void setNonAliasAttributes(GlobalDecl gd, mlir::Operation *op);
/// Map source language used to a CIR attribute.
cir::SourceLanguage getCIRSourceLanguage() const;
};
} // namespace CIRGen

View File

@ -424,6 +424,44 @@ cir::ConstVectorAttr::verify(function_ref<InFlightDiagnostic()> emitError,
return elementTypeCheck;
}
//===----------------------------------------------------------------------===//
// CIR VTableAttr
//===----------------------------------------------------------------------===//
LogicalResult cir::VTableAttr::verify(
llvm::function_ref<mlir::InFlightDiagnostic()> emitError, mlir::Type type,
mlir::ArrayAttr data) {
auto sTy = mlir::dyn_cast_if_present<cir::RecordType>(type);
if (!sTy)
return emitError() << "expected !cir.record type result";
if (sTy.getMembers().empty() || data.empty())
return emitError() << "expected record type with one or more subtype";
if (cir::ConstRecordAttr::verify(emitError, type, data).failed())
return failure();
for (const auto &element : data.getAsRange<mlir::Attribute>()) {
const auto &constArrayAttr = mlir::dyn_cast<cir::ConstArrayAttr>(element);
if (!constArrayAttr)
return emitError() << "expected constant array subtype";
LogicalResult eltTypeCheck = success();
auto arrayElts = mlir::cast<ArrayAttr>(constArrayAttr.getElts());
arrayElts.walkImmediateSubElements(
[&](mlir::Attribute attr) {
if (mlir::isa<ConstPtrAttr, GlobalViewAttr>(attr))
return;
eltTypeCheck = emitError()
<< "expected GlobalViewAttr or ConstPtrAttr";
},
[&](mlir::Type type) {});
if (eltTypeCheck.failed())
return eltTypeCheck;
}
return success();
}
//===----------------------------------------------------------------------===//
// CIR Dialect
//===----------------------------------------------------------------------===//

View File

@ -342,7 +342,8 @@ static LogicalResult checkConstantTypes(mlir::Operation *op, mlir::Type opType,
if (mlir::isa<cir::ConstArrayAttr, cir::ConstVectorAttr,
cir::ConstComplexAttr, cir::ConstRecordAttr,
cir::GlobalViewAttr, cir::PoisonAttr>(attrType))
cir::GlobalViewAttr, cir::PoisonAttr, cir::VTableAttr>(
attrType))
return success();
assert(isa<TypedAttr>(attrType) && "What else could we be looking at here?");

View File

@ -4,6 +4,7 @@ add_clang_library(MLIRCIRTransforms
FlattenCFG.cpp
HoistAllocas.cpp
LoweringPrepare.cpp
GotoSolver.cpp
DEPENDS
MLIRCIRPassIncGen

View File

@ -0,0 +1,57 @@
//====- GotoSolver.cpp -----------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "PassDetail.h"
#include "clang/CIR/Dialect/IR/CIRDialect.h"
#include "clang/CIR/Dialect/Passes.h"
#include "llvm/Support/TimeProfiler.h"
#include <memory>
using namespace mlir;
using namespace cir;
namespace {
struct GotoSolverPass : public GotoSolverBase<GotoSolverPass> {
GotoSolverPass() = default;
void runOnOperation() override;
};
static void process(cir::FuncOp func) {
mlir::OpBuilder rewriter(func.getContext());
llvm::StringMap<Block *> labels;
llvm::SmallVector<cir::GotoOp, 4> gotos;
func.getBody().walk([&](mlir::Operation *op) {
if (auto lab = dyn_cast<cir::LabelOp>(op)) {
// Will construct a string copy inplace. Safely erase the label
labels.try_emplace(lab.getLabel(), lab->getBlock());
lab.erase();
} else if (auto goTo = dyn_cast<cir::GotoOp>(op)) {
gotos.push_back(goTo);
}
});
for (auto goTo : gotos) {
mlir::OpBuilder::InsertionGuard guard(rewriter);
rewriter.setInsertionPoint(goTo);
Block *dest = labels[goTo.getLabel()];
cir::BrOp::create(rewriter, goTo.getLoc(), dest);
goTo.erase();
}
}
void GotoSolverPass::runOnOperation() {
llvm::TimeTraceScope scope("Goto Solver");
getOperation()->walk(&process);
}
} // namespace
std::unique_ptr<Pass> mlir::createGotoSolverPass() {
return std::make_unique<GotoSolverPass>();
}

View File

@ -45,6 +45,7 @@ namespace mlir {
void populateCIRPreLoweringPasses(OpPassManager &pm) {
pm.addPass(createHoistAllocasPass());
pm.addPass(createCIRFlattenCFGPass());
pm.addPass(createGotoSolverPass());
}
} // namespace mlir

View File

@ -4184,7 +4184,14 @@ llvm::DICompositeType *CGDebugInfo::CreateLimitedType(const RecordType *Ty) {
break;
}
RegionMap[RD].reset(RealDecl);
if (auto *CTSD =
dyn_cast<ClassTemplateSpecializationDecl>(Ty->getOriginalDecl())) {
CXXRecordDecl *TemplateDecl =
CTSD->getSpecializedTemplate()->getTemplatedDecl();
RegionMap[TemplateDecl].reset(RealDecl);
} else {
RegionMap[RD].reset(RealDecl);
}
TypeCache[QualType(Ty, 0).getAsOpaquePtr()].reset(RealDecl);
if (const auto *TSpecial = dyn_cast<ClassTemplateSpecializationDecl>(RD))

View File

@ -977,6 +977,8 @@ public:
ApplyInlineDebugLocation(CodeGenFunction &CGF, GlobalDecl InlinedFn);
/// Restore everything back to the original state.
~ApplyInlineDebugLocation();
ApplyInlineDebugLocation(const ApplyInlineDebugLocation &) = delete;
ApplyInlineDebugLocation &operator=(ApplyInlineDebugLocation &) = delete;
};
class SanitizerDebugLocation {
@ -988,6 +990,8 @@ public:
ArrayRef<SanitizerKind::SanitizerOrdinal> Ordinals,
SanitizerHandler Handler);
~SanitizerDebugLocation();
SanitizerDebugLocation(const SanitizerDebugLocation &) = delete;
SanitizerDebugLocation &operator=(SanitizerDebugLocation &) = delete;
};
} // namespace CodeGen

View File

@ -466,6 +466,14 @@ llvm::Constant *CodeGenModule::getConstantSignedPointer(
OtherDiscriminator);
}
llvm::Constant *
CodeGen::getConstantSignedPointer(CodeGenModule &CGM, llvm::Constant *Pointer,
unsigned Key, llvm::Constant *StorageAddress,
llvm::ConstantInt *OtherDiscriminator) {
return CGM.getConstantSignedPointer(Pointer, Key, StorageAddress,
OtherDiscriminator);
}
/// If applicable, sign a given constant function pointer with the ABI rules for
/// functionType.
llvm::Constant *CodeGenModule::getFunctionPointer(llvm::Constant *Pointer,

View File

@ -1409,13 +1409,6 @@ void ToolChain::addSystemFrameworkInclude(const llvm::opt::ArgList &DriverArgs,
CC1Args.push_back(DriverArgs.MakeArgString(Path));
}
/// Utility function to add a system include directory to CC1 arguments.
void ToolChain::addSystemInclude(const ArgList &DriverArgs,
ArgStringList &CC1Args, const Twine &Path) {
CC1Args.push_back("-internal-isystem");
CC1Args.push_back(DriverArgs.MakeArgString(Path));
}
/// Utility function to add a system include directory with extern "C"
/// semantics to CC1 arguments.
///
@ -1438,6 +1431,14 @@ void ToolChain::addExternCSystemIncludeIfExists(const ArgList &DriverArgs,
addExternCSystemInclude(DriverArgs, CC1Args, Path);
}
/// Utility function to add a system include directory to CC1 arguments.
/*static*/ void ToolChain::addSystemInclude(const ArgList &DriverArgs,
ArgStringList &CC1Args,
const Twine &Path) {
CC1Args.push_back("-internal-isystem");
CC1Args.push_back(DriverArgs.MakeArgString(Path));
}
/// Utility function to add a list of system framework directories to CC1.
void ToolChain::addSystemFrameworkIncludes(const ArgList &DriverArgs,
ArgStringList &CC1Args,

View File

@ -534,7 +534,14 @@ void Flang::addTargetOptions(const ArgList &Args,
}
Args.addAllArgs(CmdArgs,
{options::OPT_fverbose_asm, options::OPT_fno_verbose_asm});
{options::OPT_fverbose_asm, options::OPT_fno_verbose_asm,
options::OPT_fatomic_ignore_denormal_mode,
options::OPT_fno_atomic_ignore_denormal_mode,
options::OPT_fatomic_fine_grained_memory,
options::OPT_fno_atomic_fine_grained_memory,
options::OPT_fatomic_remote_memory,
options::OPT_fno_atomic_remote_memory,
options::OPT_munsafe_fp_atomics});
}
void Flang::addOffloadOptions(Compilation &C, const InputInfoList &Inputs,

View File

@ -2123,10 +2123,11 @@ void Generic_GCC::GCCInstallationDetector::init(
StringRef TripleText =
llvm::sys::path::filename(llvm::sys::path::parent_path(InstallDir));
Version = GCCVersion::Parse(VersionText);
GCCTriple.setTriple(TripleText);
GCCInstallPath = std::string(InstallDir);
GCCParentLibPath = GCCInstallPath + "/../../..";
SelectedInstallation.Version = GCCVersion::Parse(VersionText);
SelectedInstallation.GCCTriple.setTriple(TripleText);
SelectedInstallation.GCCInstallPath = std::string(InstallDir);
SelectedInstallation.GCCParentLibPath =
SelectedInstallation.GCCInstallPath + "/../../..";
IsValid = true;
}
return;
@ -2186,7 +2187,7 @@ void Generic_GCC::GCCInstallationDetector::init(
// Loop over the various components which exist and select the best GCC
// installation available. GCC installs are ranked by version number.
const GCCVersion VersionZero = GCCVersion::Parse("0.0.0");
Version = VersionZero;
SelectedInstallation.Version = VersionZero;
for (const std::string &Prefix : Prefixes) {
auto &VFS = D.getVFS();
if (!VFS.exists(Prefix))
@ -2214,7 +2215,7 @@ void Generic_GCC::GCCInstallationDetector::init(
}
// Skip other prefixes once a GCC installation is found.
if (Version > VersionZero)
if (SelectedInstallation.Version > VersionZero)
break;
}
}
@ -2223,14 +2224,17 @@ void Generic_GCC::GCCInstallationDetector::print(raw_ostream &OS) const {
for (const auto &InstallPath : CandidateGCCInstallPaths)
OS << "Found candidate GCC installation: " << InstallPath << "\n";
if (!GCCInstallPath.empty())
OS << "Selected GCC installation: " << GCCInstallPath << "\n";
if (!SelectedInstallation.GCCInstallPath.empty())
OS << "Selected GCC installation: " << SelectedInstallation.GCCInstallPath
<< "\n";
for (const auto &Multilib : Multilibs)
OS << "Candidate multilib: " << Multilib << "\n";
if (Multilibs.size() != 0 || !SelectedMultilib.isDefault())
OS << "Selected multilib: " << SelectedMultilib << "\n";
if (Multilibs.size() != 0 ||
!SelectedInstallation.SelectedMultilib.isDefault())
OS << "Selected multilib: " << SelectedInstallation.SelectedMultilib
<< "\n";
}
bool Generic_GCC::GCCInstallationDetector::getBiarchSibling(Multilib &M) const {
@ -2768,14 +2772,50 @@ bool Generic_GCC::GCCInstallationDetector::ScanGCCForMultilibs(
}
Multilibs = Detected.Multilibs;
SelectedMultilib = Detected.SelectedMultilibs.empty()
? Multilib()
: Detected.SelectedMultilibs.back();
SelectedInstallation.SelectedMultilib =
Detected.SelectedMultilibs.empty() ? Multilib()
: Detected.SelectedMultilibs.back();
BiarchSibling = Detected.BiarchSibling;
return true;
}
bool Generic_GCC::GCCInstallationDetector::SelectGCCInstallationDirectory(
const SmallVector<Generic_GCC::GCCInstallCandidate, 3> &Installations,
const ArgList &Args,
Generic_GCC::GCCInstallCandidate &SelectedInstallation) const {
if (Installations.empty())
return false;
SelectedInstallation =
*max_element(Installations, [](const auto &Max, const auto &I) {
return I.Version > Max.Version;
});
// FIXME Start selecting installation with libstdc++ in clang 22,
// using the current way of selecting the installation as a fallback
// only. For now, warn if the installation with libstdc++ differs
// from SelectedInstallation.
const GCCInstallCandidate *InstallWithIncludes = nullptr;
for (const auto &I : Installations) {
if ((!InstallWithIncludes || I.Version > InstallWithIncludes->Version) &&
GCCInstallationHasLibStdcxxIncludePaths(I, Args))
InstallWithIncludes = &I;
}
if (InstallWithIncludes && SelectedInstallation.GCCInstallPath !=
InstallWithIncludes->GCCInstallPath)
D.Diag(diag::warn_drv_gcc_install_dir_libstdcxx)
<< InstallWithIncludes->GCCInstallPath
<< SelectedInstallation.GCCInstallPath;
// TODO Warn if SelectedInstallation does not contain libstdc++ includes
// although compiler flags indicate that it is required (C++ compilation,
// libstdc++ not explicitly disabled).
return true;
}
void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple(
const llvm::Triple &TargetTriple, const ArgList &Args,
const std::string &LibDir, StringRef CandidateTriple,
@ -2805,6 +2845,7 @@ void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple(
TargetTriple.getVendor() == llvm::Triple::Freescale ||
TargetTriple.getVendor() == llvm::Triple::OpenEmbedded}};
SmallVector<GCCInstallCandidate, 3> Installations;
for (auto &Suffix : Suffixes) {
if (!Suffix.Active)
continue;
@ -2822,23 +2863,31 @@ void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple(
continue; // Saw this path before; no need to look at it again.
if (CandidateVersion.isOlderThan(4, 1, 1))
continue;
if (CandidateVersion <= Version)
if (CandidateVersion <= SelectedInstallation.Version && IsValid)
continue;
if (!ScanGCCForMultilibs(TargetTriple, Args, LI->path(),
NeedsBiarchSuffix))
continue;
Version = CandidateVersion;
GCCTriple.setTriple(CandidateTriple);
GCCInstallCandidate Installation;
Installation.Version = CandidateVersion;
Installation.GCCTriple.setTriple(CandidateTriple);
// FIXME: We hack together the directory name here instead of
// using LI to ensure stable path separators across Windows and
// Linux.
GCCInstallPath = (LibDir + "/" + LibSuffix + "/" + VersionText).str();
GCCParentLibPath = (GCCInstallPath + "/../" + Suffix.ReversePath).str();
IsValid = true;
Installation.GCCInstallPath =
(LibDir + "/" + LibSuffix + "/" + VersionText).str();
Installation.GCCParentLibPath =
(Installation.GCCInstallPath + "/../" + Suffix.ReversePath).str();
Installation.SelectedMultilib = getMultilib();
Installations.push_back(Installation);
}
}
IsValid |=
SelectGCCInstallationDirectory(Installations, Args, SelectedInstallation);
}
bool Generic_GCC::GCCInstallationDetector::ScanGentooConfigs(
@ -2916,10 +2965,12 @@ bool Generic_GCC::GCCInstallationDetector::ScanGentooGccConfig(
NeedsBiarchSuffix))
continue;
Version = GCCVersion::Parse(ActiveVersion.second);
GCCInstallPath = GentooPath;
GCCParentLibPath = GentooPath + std::string("/../../..");
GCCTriple.setTriple(ActiveVersion.first);
SelectedInstallation.Version =
GCCVersion::Parse(ActiveVersion.second);
SelectedInstallation.GCCInstallPath = GentooPath;
SelectedInstallation.GCCParentLibPath =
GentooPath + std::string("/../../..");
SelectedInstallation.GCCTriple.setTriple(ActiveVersion.first);
IsValid = true;
return true;
}
@ -3122,8 +3173,9 @@ void Generic_GCC::AddMultilibIncludeArgs(const ArgList &DriverArgs,
// gcc TOOL_INCLUDE_DIR.
const llvm::Triple &GCCTriple = GCCInstallation.getTriple();
std::string LibPath(GCCInstallation.getParentLibPath());
addSystemInclude(DriverArgs, CC1Args,
Twine(LibPath) + "/../" + GCCTriple.str() + "/include");
ToolChain::addSystemInclude(DriverArgs, CC1Args,
Twine(LibPath) + "/../" + GCCTriple.str() +
"/include");
const auto &Callback = Multilibs.includeDirsCallback();
if (Callback) {
@ -3210,12 +3262,14 @@ Generic_GCC::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
return;
}
bool Generic_GCC::addLibStdCXXIncludePaths(Twine IncludeDir, StringRef Triple,
Twine IncludeSuffix,
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args,
bool DetectDebian) const {
if (!getVFS().exists(IncludeDir))
static bool addLibStdCXXIncludePaths(llvm::vfs::FileSystem &vfs,
Twine IncludeDir, StringRef Triple,
Twine IncludeSuffix,
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args,
bool DetectDebian = false) {
if (!vfs.exists(IncludeDir))
return false;
// Debian native gcc uses g++-multiarch-incdir.diff which uses
@ -3227,39 +3281,48 @@ bool Generic_GCC::addLibStdCXXIncludePaths(Twine IncludeDir, StringRef Triple,
std::string Path =
(Include + "/" + Triple + Dir.substr(Include.size()) + IncludeSuffix)
.str();
if (DetectDebian && !getVFS().exists(Path))
if (DetectDebian && !vfs.exists(Path))
return false;
// GPLUSPLUS_INCLUDE_DIR
addSystemInclude(DriverArgs, CC1Args, IncludeDir);
ToolChain::addSystemInclude(DriverArgs, CC1Args, IncludeDir);
// GPLUSPLUS_TOOL_INCLUDE_DIR. If Triple is not empty, add a target-dependent
// include directory.
if (DetectDebian)
addSystemInclude(DriverArgs, CC1Args, Path);
ToolChain::addSystemInclude(DriverArgs, CC1Args, Path);
else if (!Triple.empty())
addSystemInclude(DriverArgs, CC1Args,
IncludeDir + "/" + Triple + IncludeSuffix);
ToolChain::addSystemInclude(DriverArgs, CC1Args,
IncludeDir + "/" + Triple + IncludeSuffix);
// GPLUSPLUS_BACKWARD_INCLUDE_DIR
addSystemInclude(DriverArgs, CC1Args, IncludeDir + "/backward");
ToolChain::addSystemInclude(DriverArgs, CC1Args, IncludeDir + "/backward");
return true;
}
bool Generic_GCC::addGCCLibStdCxxIncludePaths(
const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
StringRef DebianMultiarch) const {
assert(GCCInstallation.isValid());
bool Generic_GCC::addLibStdCXXIncludePaths(Twine IncludeDir, StringRef Triple,
Twine IncludeSuffix,
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args,
bool DetectDebian) const {
return ::addLibStdCXXIncludePaths(getVFS(), IncludeDir, Triple, IncludeSuffix,
DriverArgs, CC1Args, DetectDebian);
}
bool Generic_GCC::GCCInstallCandidate::addGCCLibStdCxxIncludePaths(
llvm::vfs::FileSystem &vfs, const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args, StringRef DebianMultiarch) const {
// By default, look for the C++ headers in an include directory adjacent to
// the lib directory of the GCC installation. Note that this is expect to be
// equivalent to '/usr/include/c++/X.Y' in almost all cases.
StringRef LibDir = GCCInstallation.getParentLibPath();
StringRef InstallDir = GCCInstallation.getInstallPath();
StringRef TripleStr = GCCInstallation.getTriple().str();
const Multilib &Multilib = GCCInstallation.getMultilib();
const GCCVersion &Version = GCCInstallation.getVersion();
StringRef LibDir = getParentLibPath();
StringRef InstallDir = getInstallPath();
StringRef TripleStr = getTriple().str();
const Multilib &Multilib = getMultilib();
const GCCVersion &Version = getVersion();
// Try /../$triple/include/c++/$version (gcc --print-multiarch is not empty).
if (addLibStdCXXIncludePaths(
if (::addLibStdCXXIncludePaths(
vfs,
LibDir.str() + "/../" + TripleStr + "/include/c++/" + Version.Text,
TripleStr, Multilib.includeSuffix(), DriverArgs, CC1Args))
return true;
@ -3267,22 +3330,24 @@ bool Generic_GCC::addGCCLibStdCxxIncludePaths(
// Try /gcc/$triple/$version/include/c++/ (gcc --print-multiarch is not
// empty). Like above but for GCC built with
// --enable-version-specific-runtime-libs.
if (addLibStdCXXIncludePaths(LibDir.str() + "/gcc/" + TripleStr + "/" +
Version.Text + "/include/c++/",
TripleStr, Multilib.includeSuffix(), DriverArgs,
CC1Args))
if (::addLibStdCXXIncludePaths(vfs,
LibDir.str() + "/gcc/" + TripleStr + "/" +
Version.Text + "/include/c++/",
TripleStr, Multilib.includeSuffix(),
DriverArgs, CC1Args))
return true;
// Detect Debian g++-multiarch-incdir.diff.
if (addLibStdCXXIncludePaths(LibDir.str() + "/../include/c++/" + Version.Text,
DebianMultiarch, Multilib.includeSuffix(),
DriverArgs, CC1Args, /*Debian=*/true))
if (::addLibStdCXXIncludePaths(
vfs, LibDir.str() + "/../include/c++/" + Version.Text,
DebianMultiarch, Multilib.includeSuffix(), DriverArgs, CC1Args,
/*Debian=*/true))
return true;
// Try /../include/c++/$version (gcc --print-multiarch is empty).
if (addLibStdCXXIncludePaths(LibDir.str() + "/../include/c++/" + Version.Text,
TripleStr, Multilib.includeSuffix(), DriverArgs,
CC1Args))
if (::addLibStdCXXIncludePaths(
vfs, LibDir.str() + "/../include/c++/" + Version.Text, TripleStr,
Multilib.includeSuffix(), DriverArgs, CC1Args))
return true;
// Otherwise, fall back on a bunch of options which don't use multiarch
@ -3297,20 +3362,50 @@ bool Generic_GCC::addGCCLibStdCxxIncludePaths(
};
for (const auto &IncludePath : LibStdCXXIncludePathCandidates) {
if (addLibStdCXXIncludePaths(IncludePath, TripleStr,
Multilib.includeSuffix(), DriverArgs, CC1Args))
if (::addLibStdCXXIncludePaths(vfs, IncludePath, TripleStr,
Multilib.includeSuffix(), DriverArgs,
CC1Args))
return true;
}
return false;
}
bool Generic_GCC::GCCInstallationDetector::
GCCInstallationHasLibStdcxxIncludePaths(
const GCCInstallCandidate &GCCInstallation,
const llvm::opt::ArgList &DriverArgs) const {
StringRef DebianMultiarch =
TripleToDebianMultiarch(GCCInstallation.getTriple());
// The following function checks for libstdc++ include paths and
// adds them to the provided argument list. Here we just need the
// check.
llvm::opt::ArgStringList dummyCC1Args;
return GCCInstallation.addGCCLibStdCxxIncludePaths(
D.getVFS(), DriverArgs, dummyCC1Args, DebianMultiarch);
}
bool Generic_GCC::addGCCLibStdCxxIncludePaths(
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const {
assert(GCCInstallation.isValid());
// Detect Debian g++-multiarch-incdir.diff.
StringRef DebianMultiarch =
GCCInstallation.TripleToDebianMultiarch(GCCInstallation.getTriple());
return GCCInstallation.getSelectedInstallation().addGCCLibStdCxxIncludePaths(
getVFS(), DriverArgs, CC1Args, DebianMultiarch);
}
void
Generic_GCC::addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const {
if (GCCInstallation.isValid()) {
addGCCLibStdCxxIncludePaths(DriverArgs, CC1Args,
GCCInstallation.getTriple().str());
}
if (!GCCInstallation.isValid())
return;
GCCInstallation.getSelectedInstallation().addGCCLibStdCxxIncludePaths(
getVFS(), DriverArgs, CC1Args, GCCInstallation.getTriple().str());
}
llvm::opt::DerivedArgList *

View File

@ -184,46 +184,18 @@ public:
bool operator>=(const GCCVersion &RHS) const { return !(*this < RHS); }
};
/// This is a class to find a viable GCC installation for Clang to
/// use.
///
/// This class tries to find a GCC installation on the system, and report
/// information about it. It starts from the host information provided to the
/// Driver, and has logic for fuzzing that where appropriate.
class GCCInstallationDetector {
bool IsValid;
llvm::Triple GCCTriple;
const Driver &D;
struct GCCInstallCandidate {
// FIXME: These might be better as path objects.
std::string GCCInstallPath;
std::string GCCParentLibPath;
llvm::Triple GCCTriple;
/// The primary multilib appropriate for the given flags.
Multilib SelectedMultilib;
/// On Biarch systems, this corresponds to the default multilib when
/// targeting the non-default multilib. Otherwise, it is empty.
std::optional<Multilib> BiarchSibling;
GCCVersion Version;
// We retain the list of install paths that were considered and rejected in
// order to print out detailed information in verbose mode.
std::set<std::string> CandidateGCCInstallPaths;
/// The set of multilibs that the detected installation supports.
MultilibSet Multilibs;
// Gentoo-specific toolchain configurations are stored here.
const std::string GentooConfigDir = "/etc/env.d/gcc";
public:
explicit GCCInstallationDetector(const Driver &D) : IsValid(false), D(D) {}
void init(const llvm::Triple &TargetTriple, const llvm::opt::ArgList &Args);
/// Check whether we detected a valid GCC install.
bool isValid() const { return IsValid; }
/// Get the GCC triple for the detected install.
const llvm::Triple &getTriple() const { return GCCTriple; }
@ -236,6 +208,88 @@ public:
/// Get the detected Multilib
const Multilib &getMultilib() const { return SelectedMultilib; }
/// Get the detected GCC version string.
const GCCVersion &getVersion() const { return Version; }
bool addGCCLibStdCxxIncludePaths(llvm::vfs::FileSystem &vfs,
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args,
StringRef DebianMultiarch) const;
};
/// This is a class to find a viable GCC installation for Clang to
/// use.
///
/// This class tries to find a GCC installation on the system, and report
/// information about it. It starts from the host information provided to the
/// Driver, and has logic for fuzzing that where appropriate.
class GCCInstallationDetector {
bool IsValid;
const Driver &D;
GCCInstallCandidate SelectedInstallation;
/// On Biarch systems, this corresponds to the default multilib when
/// targeting the non-default multilib. Otherwise, it is empty.
std::optional<Multilib> BiarchSibling;
// We retain the list of install paths that were considered and rejected in
// order to print out detailed information in verbose mode.
std::set<std::string> CandidateGCCInstallPaths;
/// The set of multilibs that the detected installation supports.
MultilibSet Multilibs;
// Gentoo-specific toolchain configurations are stored here.
const std::string GentooConfigDir = "/etc/env.d/gcc";
public:
/// Function for converting a triple to a Debian multiarch. The
/// toolchains use this to adjust the target specific component of
/// include paths for Debian.
std::function<StringRef(const llvm::Triple &)> TripleToDebianMultiarch =
[](const llvm::Triple &T) {
StringRef S = T.str();
return S;
};
explicit GCCInstallationDetector(const Driver &D) : IsValid(false), D(D) {}
void init(const llvm::Triple &TargetTriple, const llvm::opt::ArgList &Args);
// TODO Replace isValid by changing SelectedInstallation into
// std::optional<SelectedInstallation>
// and move all accessors for fields of GCCInstallCandidate into
// that struct.
/// Check whether we detected a valid GCC install.
bool isValid() const { return IsValid; }
const GCCInstallCandidate &getSelectedInstallation() const {
return SelectedInstallation;
}
/// Get the GCC triple for the detected install.
const llvm::Triple &getTriple() const {
return SelectedInstallation.GCCTriple;
}
/// Get the detected GCC installation path.
StringRef getInstallPath() const {
return SelectedInstallation.GCCInstallPath;
}
/// Get the detected GCC parent lib path.
StringRef getParentLibPath() const {
return SelectedInstallation.GCCParentLibPath;
}
/// Get the detected Multilib
const Multilib &getMultilib() const {
return SelectedInstallation.SelectedMultilib;
}
/// Get the whole MultilibSet
const MultilibSet &getMultilibs() const { return Multilibs; }
@ -244,7 +298,9 @@ public:
bool getBiarchSibling(Multilib &M) const;
/// Get the detected GCC version string.
const GCCVersion &getVersion() const { return Version; }
const GCCVersion &getVersion() const {
return SelectedInstallation.Version;
}
/// Print information about the detected GCC installation.
void print(raw_ostream &OS) const;
@ -262,6 +318,19 @@ public:
SmallVectorImpl<std::string> &Prefixes,
StringRef SysRoot);
/// Checks if the \p GCCInstallation has libstdc++ include
/// directories.
bool GCCInstallationHasLibStdcxxIncludePaths(
const GCCInstallCandidate &GCCInstallation,
const llvm::opt::ArgList &DriverArgs) const;
/// Select a GCC installation directory from \p Installations and
/// set \p SelectedInstallation accordingly.
bool SelectGCCInstallationDirectory(
const SmallVector<GCCInstallCandidate, 3> &Installations,
const llvm::opt::ArgList &Args,
GCCInstallCandidate &SelectedInstallation) const;
bool ScanGCCForMultilibs(const llvm::Triple &TargetTriple,
const llvm::opt::ArgList &Args, StringRef Path,
bool NeedsBiarchSuffix = false);
@ -348,8 +417,7 @@ protected:
llvm::opt::ArgStringList &CC1Args) const;
bool addGCCLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args,
StringRef DebianMultiarch) const;
llvm::opt::ArgStringList &CC) const;
bool addLibStdCXXIncludePaths(Twine IncludeDir, StringRef Triple,
Twine IncludeSuffix,

View File

@ -173,24 +173,72 @@ bool isLegalValidatorVersion(StringRef ValVersionStr, const Driver &D) {
return true;
}
std::string getSpirvExtArg(ArrayRef<std::string> SpvExtensionArgs) {
if (SpvExtensionArgs.empty()) {
return "-spirv-ext=all";
void getSpirvExtOperand(StringRef SpvExtensionArg, raw_ostream &out) {
// The extensions that are commented out are supported in DXC, but the SPIR-V
// backend does not know about them yet.
static const std::vector<StringRef> DxcSupportedExtensions = {
"SPV_KHR_16bit_storage", "SPV_KHR_device_group",
"SPV_KHR_fragment_shading_rate", "SPV_KHR_multiview",
"SPV_KHR_post_depth_coverage", "SPV_KHR_non_semantic_info",
"SPV_KHR_shader_draw_parameters", "SPV_KHR_ray_tracing",
"SPV_KHR_shader_clock", "SPV_EXT_demote_to_helper_invocation",
"SPV_EXT_descriptor_indexing", "SPV_EXT_fragment_fully_covered",
"SPV_EXT_fragment_invocation_density",
"SPV_EXT_fragment_shader_interlock", "SPV_EXT_mesh_shader",
"SPV_EXT_shader_stencil_export", "SPV_EXT_shader_viewport_index_layer",
// "SPV_AMD_shader_early_and_late_fragment_tests",
"SPV_GOOGLE_hlsl_functionality1", "SPV_GOOGLE_user_type",
"SPV_KHR_ray_query", "SPV_EXT_shader_image_int64",
"SPV_KHR_fragment_shader_barycentric", "SPV_KHR_physical_storage_buffer",
"SPV_KHR_vulkan_memory_model",
// "SPV_KHR_compute_shader_derivatives",
// "SPV_KHR_maximal_reconvergence",
"SPV_KHR_float_controls", "SPV_NV_shader_subgroup_partitioned",
// "SPV_KHR_quad_control"
};
if (SpvExtensionArg.starts_with("SPV_")) {
out << "+" << SpvExtensionArg;
return;
}
std::string LlvmOption =
(Twine("-spirv-ext=+") + SpvExtensionArgs.front()).str();
if (SpvExtensionArg.compare_insensitive("DXC") == 0) {
bool first = true;
std::string Operand;
for (StringRef E : DxcSupportedExtensions) {
if (!first)
out << ",";
else
first = false;
out << "+" << E;
}
return;
}
out << SpvExtensionArg;
return;
}
SmallString<1024> getSpirvExtArg(ArrayRef<std::string> SpvExtensionArgs) {
if (SpvExtensionArgs.empty()) {
return StringRef("-spirv-ext=all");
}
llvm::SmallString<1024> LlvmOption;
raw_svector_ostream out(LlvmOption);
out << "-spirv-ext=";
getSpirvExtOperand(SpvExtensionArgs[0], out);
SpvExtensionArgs = SpvExtensionArgs.slice(1);
for (auto Extension : SpvExtensionArgs) {
if (Extension != "KHR")
Extension = (Twine("+") + Extension).str();
LlvmOption = (Twine(LlvmOption) + "," + Extension).str();
for (StringRef Extension : SpvExtensionArgs) {
out << ",";
getSpirvExtOperand(Extension, out);
}
return LlvmOption;
}
bool isValidSPIRVExtensionName(const std::string &str) {
std::regex pattern("KHR|SPV_[a-zA-Z0-9_]+");
std::regex pattern("dxc|DXC|khr|KHR|SPV_[a-zA-Z0-9_]+");
return std::regex_match(str, pattern);
}
@ -371,7 +419,7 @@ HLSLToolChain::TranslateArgs(const DerivedArgList &Args, StringRef BoundArch,
std::vector<std::string> SpvExtensionArgs =
Args.getAllArgValues(options::OPT_fspv_extension_EQ);
if (checkExtensionArgsAreValid(SpvExtensionArgs, getDriver())) {
std::string LlvmOption = getSpirvExtArg(SpvExtensionArgs);
SmallString<1024> LlvmOption = getSpirvExtArg(SpvExtensionArgs);
DAL->AddSeparateArg(nullptr, Opts.getOption(options::OPT_mllvm),
LlvmOption);
}

View File

@ -71,6 +71,13 @@ static StringRef getOSLibDir(const llvm::Triple &Triple, const ArgList &Args) {
Hurd::Hurd(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
: Generic_ELF(D, Triple, Args) {
GCCInstallation.TripleToDebianMultiarch = [](const llvm::Triple &T) {
StringRef TripleStr = T.str();
StringRef DebianMultiarch =
T.getArch() == llvm::Triple::x86 ? "i386-gnu" : TripleStr;
return DebianMultiarch;
};
GCCInstallation.init(Triple, Args);
Multilibs = GCCInstallation.getMultilibs();
SelectedMultilibs.assign({GCCInstallation.getMultilib()});
@ -207,12 +214,7 @@ void Hurd::addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
if (!GCCInstallation.isValid())
return;
StringRef TripleStr = GCCInstallation.getTriple().str();
StringRef DebianMultiarch =
GCCInstallation.getTriple().getArch() == llvm::Triple::x86 ? "i386-gnu"
: TripleStr;
addGCCLibStdCxxIncludePaths(DriverArgs, CC1Args, DebianMultiarch);
addGCCLibStdCxxIncludePaths(DriverArgs, CC1Args);
}
void Hurd::addExtraOpts(llvm::opt::ArgStringList &CmdArgs) const {

View File

@ -211,6 +211,13 @@ static StringRef getOSLibDir(const llvm::Triple &Triple, const ArgList &Args) {
Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
: Generic_ELF(D, Triple, Args) {
GCCInstallation.TripleToDebianMultiarch = [](const llvm::Triple &T) {
StringRef TripleStr = T.str();
StringRef DebianMultiarch =
T.getArch() == llvm::Triple::x86 ? "i386-linux-gnu" : TripleStr;
return DebianMultiarch;
};
GCCInstallation.init(Triple, Args);
Multilibs = GCCInstallation.getMultilibs();
SelectedMultilibs.assign({GCCInstallation.getMultilib()});
@ -693,22 +700,15 @@ void Linux::addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
if (!GCCInstallation.isValid())
return;
// Detect Debian g++-multiarch-incdir.diff.
StringRef TripleStr = GCCInstallation.getTriple().str();
StringRef DebianMultiarch =
GCCInstallation.getTriple().getArch() == llvm::Triple::x86
? "i386-linux-gnu"
: TripleStr;
// Try generic GCC detection first.
if (Generic_GCC::addGCCLibStdCxxIncludePaths(DriverArgs, CC1Args,
DebianMultiarch))
if (Generic_GCC::addGCCLibStdCxxIncludePaths(DriverArgs, CC1Args))
return;
StringRef LibDir = GCCInstallation.getParentLibPath();
const Multilib &Multilib = GCCInstallation.getMultilib();
const GCCVersion &Version = GCCInstallation.getVersion();
StringRef TripleStr = GCCInstallation.getTriple().str();
const std::string LibStdCXXIncludePathCandidates[] = {
// Android standalone toolchain has C++ headers in yet another place.
LibDir.str() + "/../" + TripleStr.str() + "/include/c++/" + Version.Text,

View File

@ -193,10 +193,8 @@ void Managarm::addLibStdCxxIncludePaths(
if (!GCCInstallation.isValid())
return;
StringRef TripleStr = GCCInstallation.getTriple().str();
// Try generic GCC detection.
Generic_GCC::addGCCLibStdCxxIncludePaths(DriverArgs, CC1Args, TripleStr);
addGCCLibStdCxxIncludePaths(DriverArgs, CC1Args);
}
SanitizerMask Managarm::getSupportedSanitizers() const {

View File

@ -16,8 +16,7 @@
#define _NULLPTR_T
#ifdef __cplusplus
#if __cplusplus >= 201103L || \
(defined(_MSC_EXTENSIONS) && defined(_NATIVE_NULLPTR_SUPPORTED))
#if defined(_MSC_EXTENSIONS) && defined(_NATIVE_NULLPTR_SUPPORTED)
namespace std {
typedef decltype(nullptr) nullptr_t;
}

View File

@ -3721,7 +3721,7 @@ _mm_maskstore_epi64(long long *__X, __m128i __M, __m128i __Y)
/// A 256-bit vector of [8 x i32] containing the unsigned shift counts (in
/// bits).
/// \returns A 256-bit vector of [8 x i32] containing the result.
static __inline__ __m256i __DEFAULT_FN_ATTRS256
static __inline__ __m256i __DEFAULT_FN_ATTRS256_CONSTEXPR
_mm256_sllv_epi32(__m256i __X, __m256i __Y)
{
return (__m256i)__builtin_ia32_psllv8si((__v8si)__X, (__v8si)__Y);
@ -3743,7 +3743,7 @@ _mm256_sllv_epi32(__m256i __X, __m256i __Y)
/// A 128-bit vector of [4 x i32] containing the unsigned shift counts (in
/// bits).
/// \returns A 128-bit vector of [4 x i32] containing the result.
static __inline__ __m128i __DEFAULT_FN_ATTRS128
static __inline__ __m128i __DEFAULT_FN_ATTRS128_CONSTEXPR
_mm_sllv_epi32(__m128i __X, __m128i __Y)
{
return (__m128i)__builtin_ia32_psllv4si((__v4si)__X, (__v4si)__Y);
@ -3765,7 +3765,7 @@ _mm_sllv_epi32(__m128i __X, __m128i __Y)
/// A 256-bit vector of [4 x i64] containing the unsigned shift counts (in
/// bits).
/// \returns A 256-bit vector of [4 x i64] containing the result.
static __inline__ __m256i __DEFAULT_FN_ATTRS256
static __inline__ __m256i __DEFAULT_FN_ATTRS256_CONSTEXPR
_mm256_sllv_epi64(__m256i __X, __m256i __Y)
{
return (__m256i)__builtin_ia32_psllv4di((__v4di)__X, (__v4di)__Y);
@ -3787,7 +3787,7 @@ _mm256_sllv_epi64(__m256i __X, __m256i __Y)
/// A 128-bit vector of [2 x i64] containing the unsigned shift counts (in
/// bits).
/// \returns A 128-bit vector of [2 x i64] containing the result.
static __inline__ __m128i __DEFAULT_FN_ATTRS128
static __inline__ __m128i __DEFAULT_FN_ATTRS128_CONSTEXPR
_mm_sllv_epi64(__m128i __X, __m128i __Y)
{
return (__m128i)__builtin_ia32_psllv2di((__v2di)__X, (__v2di)__Y);
@ -3810,7 +3810,7 @@ _mm_sllv_epi64(__m128i __X, __m128i __Y)
/// A 256-bit vector of [8 x i32] containing the unsigned shift counts (in
/// bits).
/// \returns A 256-bit vector of [8 x i32] containing the result.
static __inline__ __m256i __DEFAULT_FN_ATTRS256
static __inline__ __m256i __DEFAULT_FN_ATTRS256_CONSTEXPR
_mm256_srav_epi32(__m256i __X, __m256i __Y)
{
return (__m256i)__builtin_ia32_psrav8si((__v8si)__X, (__v8si)__Y);
@ -3833,7 +3833,7 @@ _mm256_srav_epi32(__m256i __X, __m256i __Y)
/// A 128-bit vector of [4 x i32] containing the unsigned shift counts (in
/// bits).
/// \returns A 128-bit vector of [4 x i32] containing the result.
static __inline__ __m128i __DEFAULT_FN_ATTRS128
static __inline__ __m128i __DEFAULT_FN_ATTRS128_CONSTEXPR
_mm_srav_epi32(__m128i __X, __m128i __Y)
{
return (__m128i)__builtin_ia32_psrav4si((__v4si)__X, (__v4si)__Y);
@ -3855,7 +3855,7 @@ _mm_srav_epi32(__m128i __X, __m128i __Y)
/// A 256-bit vector of [8 x i32] containing the unsigned shift counts (in
/// bits).
/// \returns A 256-bit vector of [8 x i32] containing the result.
static __inline__ __m256i __DEFAULT_FN_ATTRS256
static __inline__ __m256i __DEFAULT_FN_ATTRS256_CONSTEXPR
_mm256_srlv_epi32(__m256i __X, __m256i __Y)
{
return (__m256i)__builtin_ia32_psrlv8si((__v8si)__X, (__v8si)__Y);
@ -3877,7 +3877,7 @@ _mm256_srlv_epi32(__m256i __X, __m256i __Y)
/// A 128-bit vector of [4 x i32] containing the unsigned shift counts (in
/// bits).
/// \returns A 128-bit vector of [4 x i32] containing the result.
static __inline__ __m128i __DEFAULT_FN_ATTRS128
static __inline__ __m128i __DEFAULT_FN_ATTRS128_CONSTEXPR
_mm_srlv_epi32(__m128i __X, __m128i __Y)
{
return (__m128i)__builtin_ia32_psrlv4si((__v4si)__X, (__v4si)__Y);
@ -3899,7 +3899,7 @@ _mm_srlv_epi32(__m128i __X, __m128i __Y)
/// A 256-bit vector of [4 x i64] containing the unsigned shift counts (in
/// bits).
/// \returns A 256-bit vector of [4 x i64] containing the result.
static __inline__ __m256i __DEFAULT_FN_ATTRS256
static __inline__ __m256i __DEFAULT_FN_ATTRS256_CONSTEXPR
_mm256_srlv_epi64(__m256i __X, __m256i __Y)
{
return (__m256i)__builtin_ia32_psrlv4di((__v4di)__X, (__v4di)__Y);
@ -3921,7 +3921,7 @@ _mm256_srlv_epi64(__m256i __X, __m256i __Y)
/// A 128-bit vector of [2 x i64] containing the unsigned shift counts (in
/// bits).
/// \returns A 128-bit vector of [2 x i64] containing the result.
static __inline__ __m128i __DEFAULT_FN_ATTRS128
static __inline__ __m128i __DEFAULT_FN_ATTRS128_CONSTEXPR
_mm_srlv_epi64(__m128i __X, __m128i __Y)
{
return (__m128i)__builtin_ia32_psrlv2di((__v2di)__X, (__v2di)__Y);

View File

@ -5601,8 +5601,10 @@ ExprResult Sema::BuiltinShuffleVector(CallExpr *TheCall) {
TheCall->getArg(1)->getEndLoc()));
} else if (numElements != numResElements) {
QualType eltType = LHSType->castAs<VectorType>()->getElementType();
resType =
Context.getVectorType(eltType, numResElements, VectorKind::Generic);
resType = resType->isExtVectorType()
? Context.getExtVectorType(eltType, numResElements)
: Context.getVectorType(eltType, numResElements,
VectorKind::Generic);
}
}

View File

@ -338,3 +338,12 @@ static void *FooTable[1] = {
}
};
int strcmp(const char *, const char *); // all-note {{passing argument to parameter here}}
#define S "\x01\x02\x03\x04\x05\x06\x07\x08"
const char _str[] = {S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7]};
const unsigned char _str2[] = {S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7]};
const int compared = strcmp(_str, (const char *)_str2); // all-error {{initializer element is not a compile-time constant}}
const int compared2 = strcmp(strcmp, _str); // all-warning {{incompatible pointer types}} \
// all-error {{initializer element is not a compile-time constant}}

View File

@ -15,7 +15,6 @@ using FourFloatsExtVec __attribute__((ext_vector_type(4))) = float;
using FourDoublesExtVec __attribute__((ext_vector_type(4))) = double;
using FourI128ExtVec __attribute__((ext_vector_type(4))) = __int128;
// Next a series of tests to make sure these operations are usable in
// constexpr functions. Template instantiations don't emit Winvalid-constexpr,
// so we have to do these as macros.
@ -875,3 +874,9 @@ void BoolVecUsage() {
constexpr auto k = ~FourBoolsExtVec{true, false, true, false};
static_assert(k[0] == false && k[1] == true && k[2] == false && k[3] == true, "");
}
using EightBoolsExtVec __attribute__((ext_vector_type(8))) = bool;
void BoolVecShuffle() {
constexpr EightBoolsExtVec a = __builtin_shufflevector(
FourBoolsExtVec{}, FourBoolsExtVec{}, 0, 1, 2, 3, 4, 5, 6, 7);
}

View File

@ -732,3 +732,8 @@ namespace LocalVarForParmVarDecl {
}
static_assert(foo(), "");
}
namespace PtrPtrCast {
void foo() { ; }
void bar(int *a) { a = (int *)(void *)(foo); }
}

View File

@ -0,0 +1,47 @@
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -fclangir -emit-cir %s -o %t.cir
// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -fclangir -emit-llvm %s -o %t-cir.ll
// RUN: FileCheck --input-file=%t-cir.ll %s -check-prefix=LLVM
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -emit-llvm %s -o %t.ll
// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG
void f(void);
void f1() {
(void (*)())f;
}
void f2() {
(*(void (*)(void))f)();
}
void test_lvalue_cast() {
(*(void (*)(int))f)(42);
}
// CIR-LABEL: cir.func{{.*}} @f()
// CIR: cir.func{{.*}} @f1()
// CIR: cir.return{{.*}}
// CIR-LABEL: cir.func{{.*}} @f2()
// CIR: cir.call @f() : () -> ()
// CIR-LABEL: cir.func{{.*}} @test_lvalue_cast()
// CIR: %[[S0:.+]] = {{.*}}@f : !cir.ptr<!cir.func<()>>{{.*}}
// CIR: %[[S1:.+]] = cir.cast{{.*}}%[[S0]] : !cir.ptr<!cir.func<()>>{{.*}}
// CIR: %[[S2:.+]] = cir.const #cir.int<42> : !s32i
// CIR: cir.call %[[S1]](%[[S2]]) : (!cir.ptr<!cir.func<(!s32i)>>, !s32i) -> ()
// LLVM-LABEL: define{{.*}} void @f1()
// LLVM: ret void
// LLVM: define{{.*}} void @f2()
// LLVM: call void @f()
// LLVM: define{{.*}} void @test_lvalue_cast()
// LLVM: call void @f(i32 42)
// OGCG-LABEL: define{{.*}} void @f1()
// OGCG: ret void
// OGCG: define{{.*}} void @f2()
// OGCG: call void @f()
// OGCG: define{{.*}} void @test_lvalue_cast()
// OGCG: call void @f(i32 noundef 42)

View File

@ -1,5 +1,7 @@
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir
// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t-cir.ll
// RUN: FileCheck --input-file=%t-cir.ll %s --check-prefix=LLVM
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll
// RUN: FileCheck --input-file=%t.ll %s --check-prefix=OGCG
@ -27,6 +29,24 @@ err:
// CIR: cir.store [[MINUS]], [[RETVAL]] : !s32i, !cir.ptr<!s32i>
// CIR: cir.br ^bb1
// LLVM: define dso_local i32 @_Z21shouldNotGenBranchReti
// LLVM: [[COND:%.*]] = load i32, ptr {{.*}}, align 4
// LLVM: [[CMP:%.*]] = icmp sgt i32 [[COND]], 5
// LLVM: br i1 [[CMP]], label %[[IFTHEN:.*]], label %[[IFEND:.*]]
// LLVM: [[IFTHEN]]:
// LLVM: br label %[[ERR:.*]]
// LLVM: [[IFEND]]:
// LLVM: br label %[[BB9:.*]]
// LLVM: [[BB9]]:
// LLVM: store i32 0, ptr %[[RETVAL:.*]], align 4
// LLVM: br label %[[BBRET:.*]]
// LLVM: [[BBRET]]:
// LLVM: [[RET:%.*]] = load i32, ptr %[[RETVAL]], align 4
// LLVM: ret i32 [[RET]]
// LLVM: [[ERR]]:
// LLVM: store i32 -1, ptr %[[RETVAL]], align 4
// LLVM: br label %10
// OGCG: define dso_local noundef i32 @_Z21shouldNotGenBranchReti
// OGCG: if.then:
// OGCG: br label %err
@ -51,6 +71,17 @@ err:
// CIR: ^bb1:
// CIR: cir.label "err"
// LLVM: define dso_local i32 @_Z15shouldGenBranchi
// LLVM: br i1 [[CMP:%.*]], label %[[IFTHEN:.*]], label %[[IFEND:.*]]
// LLVM: [[IFTHEN]]:
// LLVM: br label %[[ERR:.*]]
// LLVM: [[IFEND]]:
// LLVM: br label %[[BB9:.*]]
// LLVM: [[BB9]]:
// LLVM: br label %[[ERR]]
// LLVM: [[ERR]]:
// LLVM: ret i32 [[RET:%.*]]
// OGCG: define dso_local noundef i32 @_Z15shouldGenBranchi
// OGCG: if.then:
// OGCG: br label %err
@ -78,6 +109,15 @@ end2:
// CIR: ^bb[[#BLK3]]:
// CIR: cir.label "end2"
// LLVM: define dso_local void @_Z19severalLabelsInARowi
// LLVM: br label %[[END1:.*]]
// LLVM: [[UNRE:.*]]: ; No predecessors!
// LLVM: br label %[[END2:.*]]
// LLVM: [[END1]]:
// LLVM: br label %[[END2]]
// LLVM: [[END2]]:
// LLVM: ret
// OGCG: define dso_local void @_Z19severalLabelsInARowi
// OGCG: br label %end1
// OGCG: end1:
@ -99,6 +139,13 @@ end:
// CIR: ^bb[[#BLK2:]]:
// CIR: cir.label "end"
// LLVM: define dso_local void @_Z18severalGotosInARowi
// LLVM: br label %[[END:.*]]
// LLVM: [[UNRE:.*]]: ; No predecessors!
// LLVM: br label %[[END]]
// LLVM: [[END]]:
// LLVM: ret void
// OGCG: define dso_local void @_Z18severalGotosInARowi(i32 noundef %a) #0 {
// OGCG: br label %end
// OGCG: end:
@ -126,6 +173,14 @@ extern "C" void multiple_non_case(int v) {
// CIR: cir.call @action2()
// CIR: cir.break
// LLVM: define dso_local void @multiple_non_case
// LLVM: [[SWDEFAULT:.*]]:
// LLVM: call void @action1()
// LLVM: br label %[[L2:.*]]
// LLVM: [[L2]]:
// LLVM: call void @action2()
// LLVM: br label %[[BREAK:.*]]
// OGCG: define dso_local void @multiple_non_case
// OGCG: sw.default:
// OGCG: call void @action1()
@ -158,6 +213,26 @@ extern "C" void case_follow_label(int v) {
// CIR: cir.call @action2()
// CIR: cir.goto "label"
// LLVM: define dso_local void @case_follow_label
// LLVM: switch i32 {{.*}}, label %[[SWDEFAULT:.*]] [
// LLVM: i32 1, label %[[LABEL:.*]]
// LLVM: i32 2, label %[[CASE2:.*]]
// LLVM: ]
// LLVM: [[LABEL]]:
// LLVM: br label %[[CASE2]]
// LLVM: [[CASE2]]:
// LLVM: call void @action1()
// LLVM: br label %[[BREAK:.*]]
// LLVM: [[BREAK]]:
// LLVM: br label %[[END:.*]]
// LLVM: [[SWDEFAULT]]:
// LLVM: call void @action2()
// LLVM: br label %[[LABEL]]
// LLVM: [[END]]:
// LLVM: br label %[[RET:.*]]
// LLVM: [[RET]]:
// LLVM: ret void
// OGCG: define dso_local void @case_follow_label
// OGCG: sw.bb:
// OGCG: br label %label
@ -197,6 +272,26 @@ extern "C" void default_follow_label(int v) {
// CIR: cir.call @action2()
// CIR: cir.goto "label"
// LLVM: define dso_local void @default_follow_label
// LLVM: [[CASE1:.*]]:
// LLVM: br label %[[BB8:.*]]
// LLVM: [[BB8]]:
// LLVM: br label %[[CASE2:.*]]
// LLVM: [[CASE2]]:
// LLVM: call void @action1()
// LLVM: br label %[[BREAK:.*]]
// LLVM: [[LABEL:.*]]:
// LLVM: br label %[[SWDEFAULT:.*]]
// LLVM: [[SWDEFAULT]]:
// LLVM: call void @action2()
// LLVM: br label %[[BB9:.*]]
// LLVM: [[BB9]]:
// LLVM: br label %[[LABEL]]
// LLVM: [[BREAK]]:
// LLVM: br label %[[RET:.*]]
// LLVM: [[RET]]:
// LLVM: ret void
// OGCG: define dso_local void @default_follow_label
// OGCG: sw.bb:
// OGCG: call void @action1()

View File

@ -1,5 +1,7 @@
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir
// RUN: FileCheck --input-file=%t.cir %s --check-prefix=CIR
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t-cir.ll
// RUN: FileCheck --input-file=%t-cir.ll %s --check-prefix=LLVM
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll
// RUN: FileCheck --input-file=%t.ll %s --check-prefix=OGCG
@ -12,8 +14,8 @@ labelA:
// CIR: cir.label "labelA"
// CIR: cir.return
// Note: We are not lowering to LLVM IR via CIR at this stage because that
// process depends on the GotoSolver.
// LLVM:define dso_local void @label
// LLVM: ret void
// OGCG: define dso_local void @label
// OGCG: br label %labelA
@ -33,6 +35,11 @@ labelC:
// CIR: cir.label "labelC"
// CIR: cir.return
// LLVM: define dso_local void @multiple_labels()
// LLVM: br label %1
// LLVM: 1:
// LLVM: ret void
// OGCG: define dso_local void @multiple_labels
// OGCG: br label %labelB
// OGCG: labelB:
@ -56,6 +63,22 @@ labelD:
// CIR: }
// CIR: cir.return
// LLVM: define dso_local void @label_in_if
// LLVM: br label %3
// LLVM: 3:
// LLVM: [[LOAD:%.*]] = load i32, ptr [[COND:%.*]], align 4
// LLVM: [[CMP:%.*]] = icmp ne i32 [[LOAD]], 0
// LLVM: br i1 [[CMP]], label %6, label %9
// LLVM: 6:
// LLVM: [[LOAD2:%.*]] = load i32, ptr [[COND]], align 4
// LLVM: [[ADD1:%.*]] = add nsw i32 [[LOAD2]], 1
// LLVM: store i32 [[ADD1]], ptr [[COND]], align 4
// LLVM: br label %9
// LLVM: 9:
// LLVM: br label %10
// LLVM: 10:
// LLVM: ret void
// OGCG: define dso_local void @label_in_if
// OGCG: if.then:
// OGCG: br label %labelD
@ -80,6 +103,13 @@ void after_return() {
// CIR: cir.label "label"
// CIR: cir.br ^bb1
// LLVM: define dso_local void @after_return
// LLVM: br label %1
// LLVM: 1:
// LLVM: ret void
// LLVM: 2:
// LLVM: br label %1
// OGCG: define dso_local void @after_return
// OGCG: br label %label
// OGCG: label:
@ -97,6 +127,11 @@ void after_unreachable() {
// CIR: cir.label "label"
// CIR: cir.return
// LLVM: define dso_local void @after_unreachable
// LLVM: unreachable
// LLVM: 1:
// LLVM: ret void
// OGCG: define dso_local void @after_unreachable
// OGCG: unreachable
// OGCG: label:
@ -111,6 +146,9 @@ end:
// CIR: cir.return
// CIR: }
// LLVM: define dso_local void @labelWithoutMatch
// LLVM: ret void
// OGCG: define dso_local void @labelWithoutMatch
// OGCG: br label %end
// OGCG: end:
@ -132,6 +170,15 @@ void foo() {
// CIR: cir.label "label"
// CIR: %0 = cir.alloca !rec_S, !cir.ptr<!rec_S>, ["agg.tmp0"]
// LLVM:define dso_local void @foo() {
// LLVM: [[ALLOC:%.*]] = alloca %struct.S, i64 1, align 1
// LLVM: br label %2
// LLVM:2:
// LLVM: [[CALL:%.*]] = call %struct.S @get()
// LLVM: store %struct.S [[CALL]], ptr [[ALLOC]], align 1
// LLVM: [[LOAD:%.*]] = load %struct.S, ptr [[ALLOC]], align 1
// LLVM: call void @bar(%struct.S [[LOAD]])
// OGCG: define dso_local void @foo()
// OGCG: %agg.tmp = alloca %struct.S, align 1
// OGCG: %undef.agg.tmp = alloca %struct.S, align 1

View File

@ -0,0 +1,11 @@
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cpp.cir
// RUN: FileCheck --check-prefix=CIR-CPP --input-file=%t.cpp.cir %s
// RUN: %clang_cc1 -x c -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.c.cir
// RUN: FileCheck --check-prefix=CIR-C --input-file=%t.c.cir %s
// CIR-CPP: module attributes {{{.*}}cir.lang = #cir.lang<cxx>{{.*}}}
// CIR-C: module attributes {{{.*}}cir.lang = #cir.lang<c>{{.*}}}
int main() {
return 0;
}

View File

@ -0,0 +1,5 @@
// RUN: cir-opt %s -verify-diagnostics
// expected-error@below {{expected ::cir::SourceLanguage to be one of}}
// expected-error@below {{failed to parse CIR_SourceLanguageAttr parameter 'value'}}
module attributes {cir.lang = #cir.lang<dummy>} { }

View File

@ -1,4 +1,4 @@
// RUN: cir-opt %s -verify-diagnostics
// RUN: cir-opt %s -verify-diagnostics -split-input-file
!s8i = !cir.int<s, 8>
!u32i = !cir.int<u, 32>
@ -7,3 +7,67 @@ cir.func @reference_unknown_vtable() {
%0 = cir.vtable.address_point(@some_vtable, address_point = <index = 0, offset = 2>) : !cir.vptr
cir.return
}
// -----
!rec_S = !cir.record<struct "S" {!cir.vptr}>
!u8i = !cir.int<u, 8>
!rec_anon_struct = !cir.record<struct {!cir.array<!cir.ptr<!u8i> x 4>}>
module {
// expected-error @below {{expected !cir.record type result}}
cir.global external @_ZTV1S = #cir.vtable<{#cir.const_array<[#cir.ptr<null> : !cir.ptr<!u8i>, #cir.ptr<null> : !cir.ptr<!u8i>, #cir.global_view<@_ZN1S3keyEv> : !cir.ptr<!u8i>, #cir.global_view<@_ZN1S6nonKeyEv> : !cir.ptr<!u8i>]> : !cir.array<!cir.ptr<!u8i> x 4>}> : !cir.ptr<!rec_anon_struct>
cir.func private dso_local @_ZN1S3keyEv(%arg0: !cir.ptr<!rec_S>)
cir.func private dso_local @_ZN1S6nonKeyEv(%arg0: !cir.ptr<!rec_S>)
}
// -----
!rec_S = !cir.record<struct "S" {!cir.vptr}>
!u8i = !cir.int<u, 8>
!rec_anon_struct = !cir.record<struct {}>
module {
// expected-error @below {{expected record type with one or more subtype}}
cir.global external @_ZTV1S = #cir.vtable<{}> : !rec_anon_struct {alignment = 8 : i64}
cir.func private dso_local @_ZN1S3keyEv(%arg0: !cir.ptr<!rec_S>)
cir.func private dso_local @_ZN1S6nonKeyEv(%arg0: !cir.ptr<!rec_S>)
}
// -----
!rec_S = !cir.record<struct "S" {!cir.vptr}>
!u8i = !cir.int<u, 8>
!rec_anon_struct = !cir.record<struct {!cir.ptr<!u8i>}>
module {
// expected-error @below {{expected constant array subtype}}
cir.global external @_ZTV1S = #cir.vtable<{#cir.ptr<null> : !cir.ptr<!u8i>}> : !rec_anon_struct {alignment = 8 : i64}
cir.func private dso_local @_ZN1S3keyEv(%arg0: !cir.ptr<!rec_S>)
cir.func private dso_local @_ZN1S6nonKeyEv(%arg0: !cir.ptr<!rec_S>)
}
// -----
!rec_S = !cir.record<struct "S" {!cir.vptr}>
!u64i = !cir.int<u, 64>
!rec_anon_struct = !cir.record<struct {!cir.array<!u64i x 4>}>
module {
// expected-error @below {{expected GlobalViewAttr or ConstPtrAttr}}
cir.global external @_ZTV1S = #cir.vtable<{#cir.const_array<[#cir.int<1> : !u64i, #cir.int<1> : !u64i, #cir.int<3> : !u64i, #cir.int<4> : !u64i]> : !cir.array<!u64i x 4>}> : !rec_anon_struct {alignment = 8 : i64}
cir.func private dso_local @_ZN1S3keyEv(%arg0: !cir.ptr<!rec_S>)
cir.func private dso_local @_ZN1S6nonKeyEv(%arg0: !cir.ptr<!rec_S>)
}
// -----
!rec_Q = !cir.record<struct "Q" {!cir.vptr}>
!rec_S = !cir.record<struct "S" {!cir.vptr}>
!rec_S2 = !cir.record<struct "S2" {!rec_Q, !rec_S}>
!u8i = !cir.int<u, 8>
!rec_anon_struct = !cir.record<struct {!cir.array<!cir.ptr<!u8i> x 4>, !cir.ptr<!u8i>}>
module {
// expected-error @below {{expected constant array subtype}}
cir.global external @_ZTV2S2 = #cir.vtable<{#cir.const_array<[#cir.ptr<null> : !cir.ptr<!u8i>, #cir.ptr<null> : !cir.ptr<!u8i>, #cir.global_view<@_ZN1S3keyEv> : !cir.ptr<!u8i>, #cir.global_view<@_ZN1S6nonKeyEv> : !cir.ptr<!u8i>]> : !cir.array<!cir.ptr<!u8i> x 4>, #cir.ptr<null> : !cir.ptr<!u8i>}> : !rec_anon_struct {alignment = 8 : i64}
cir.func private dso_local @_ZN1S3keyEv(%arg0: !cir.ptr<!rec_S>)
cir.func private dso_local @_ZN1S6nonKeyEv(%arg0: !cir.ptr<!rec_S>)
cir.func private dso_local @_ZN2S23keyEv(%arg0: !cir.ptr<!rec_S2>)
}

View File

@ -0,0 +1,12 @@
// RUN: cir-opt %s -split-input-file -o %t.cir
// RUN: FileCheck --input-file=%t.cir %s
// Should parse and print C source language attribute.
module attributes {cir.lang = #cir.lang<c>} { }
// CHECK: module attributes {cir.lang = #cir.lang<c>}
// -----
// Should parse and print C++ source language attribute.
module attributes {cir.lang = #cir.lang<cxx>} { }
// CHECK: module attributes {cir.lang = #cir.lang<cxx>}

View File

@ -0,0 +1,19 @@
// RUN: cir-opt %s | FileCheck %s
!rec_Q = !cir.record<struct "Q" {!cir.vptr}>
!rec_S = !cir.record<struct "S" {!cir.vptr}>
!rec_S2 = !cir.record<struct "S2" {!rec_Q, !rec_S}>
!u8i = !cir.int<u, 8>
!rec_anon_struct = !cir.record<struct {!cir.array<!cir.ptr<!u8i> x 4>}>
!rec_anon_struct1 = !cir.record<struct {!cir.array<!cir.ptr<!u8i> x 4>, !cir.array<!cir.ptr<!u8i> x 3>}>
module {
cir.global external @_ZTV1S = #cir.vtable<{#cir.const_array<[#cir.ptr<null> : !cir.ptr<!u8i>, #cir.ptr<null> : !cir.ptr<!u8i>, #cir.global_view<@_ZN1S3keyEv> : !cir.ptr<!u8i>, #cir.global_view<@_ZN1S6nonKeyEv> : !cir.ptr<!u8i>]> : !cir.array<!cir.ptr<!u8i> x 4>}> : !rec_anon_struct {alignment = 8 : i64}
// CHECK: cir.global external @_ZTV1S = #cir.vtable<{#cir.const_array<[#cir.ptr<null> : !cir.ptr<!u8i>, #cir.ptr<null> : !cir.ptr<!u8i>, #cir.global_view<@_ZN1S3keyEv> : !cir.ptr<!u8i>, #cir.global_view<@_ZN1S6nonKeyEv> : !cir.ptr<!u8i>]> : !cir.array<!cir.ptr<!u8i> x 4>}> : !rec_anon_struct {alignment = 8 : i64}
cir.global external @_ZTV2S2 = #cir.vtable<{#cir.const_array<[#cir.ptr<null> : !cir.ptr<!u8i>, #cir.ptr<null> : !cir.ptr<!u8i>, #cir.global_view<@_ZN1S3keyEv> : !cir.ptr<!u8i>, #cir.global_view<@_ZN1S6nonKeyEv> : !cir.ptr<!u8i>]> : !cir.array<!cir.ptr<!u8i> x 4>, #cir.const_array<[#cir.ptr<-8 : i64> : !cir.ptr<!u8i>, #cir.ptr<null> : !cir.ptr<!u8i>, #cir.global_view<@_ZN2S23keyEv> : !cir.ptr<!u8i>]> : !cir.array<!cir.ptr<!u8i> x 3>}> : !rec_anon_struct1 {alignment = 8 : i64}
// CHECK: cir.global external @_ZTV2S2 = #cir.vtable<{#cir.const_array<[#cir.ptr<null> : !cir.ptr<!u8i>, #cir.ptr<null> : !cir.ptr<!u8i>, #cir.global_view<@_ZN1S3keyEv> : !cir.ptr<!u8i>, #cir.global_view<@_ZN1S6nonKeyEv> : !cir.ptr<!u8i>]> : !cir.array<!cir.ptr<!u8i> x 4>, #cir.const_array<[#cir.ptr<-8 : i64> : !cir.ptr<!u8i>, #cir.ptr<null> : !cir.ptr<!u8i>, #cir.global_view<@_ZN2S23keyEv> : !cir.ptr<!u8i>]> : !cir.array<!cir.ptr<!u8i> x 3>}> : !rec_anon_struct1 {alignment = 8 : i64}
cir.func private dso_local @_ZN1S3keyEv(%arg0: !cir.ptr<!rec_S>)
cir.func private dso_local @_ZN1S6nonKeyEv(%arg0: !cir.ptr<!rec_S>)
cir.func private dso_local @_ZN2S23keyEv(%arg0: !cir.ptr<!rec_S2>)
}

View File

@ -0,0 +1,52 @@
// RUN: cir-opt %s --pass-pipeline='builtin.module(cir-to-llvm,canonicalize{region-simplify=disabled})' -o - | FileCheck %s -check-prefix=MLIR
!s32i = !cir.int<s, 32>
module {
cir.func @gotoFromIf(%arg0: !s32i) -> !s32i {
%0 = cir.alloca !s32i, !cir.ptr<!s32i>, ["x", init] {alignment = 4 : i64}
%1 = cir.alloca !s32i, !cir.ptr<!s32i>, ["__retval"] {alignment = 4 : i64}
cir.store %arg0, %0 : !s32i, !cir.ptr<!s32i>
cir.scope {
%6 = cir.load %0 : !cir.ptr<!s32i>, !s32i
%7 = cir.const #cir.int<5> : !s32i
%8 = cir.cmp(gt, %6, %7) : !s32i, !cir.bool
cir.if %8 {
cir.goto "err"
}
}
%2 = cir.const #cir.int<0> : !s32i
cir.store %2, %1 : !s32i, !cir.ptr<!s32i>
cir.br ^bb1
^bb1:
%3 = cir.load %1 : !cir.ptr<!s32i>, !s32i
cir.return %3 : !s32i
^bb2:
cir.label "err"
%4 = cir.const #cir.int<1> : !s32i
%5 = cir.unary(minus, %4) : !s32i, !s32i
cir.store %5, %1 : !s32i, !cir.ptr<!s32i>
cir.br ^bb1
}
// MLIR: llvm.func @gotoFromIf
// MLIR: %[[#One:]] = llvm.mlir.constant(1 : i32) : i32
// MLIR: %[[#Zero:]] = llvm.mlir.constant(0 : i32) : i32
// MLIR: llvm.cond_br {{.*}}, ^bb[[#COND_YES:]], ^bb[[#COND_NO:]]
// MLIR: ^bb[[#COND_YES]]:
// MLIR: llvm.br ^bb[[#GOTO_BLK:]]
// MLIR: ^bb[[#COND_NO]]:
// MLIR: llvm.br ^bb[[#BLK:]]
// MLIR: ^bb[[#BLK]]:
// MLIR: llvm.store %[[#Zero]], %[[#Ret_val_addr:]] {{.*}}: i32, !llvm.ptr
// MLIR: llvm.br ^bb[[#RETURN:]]
// MLIR: ^bb[[#RETURN]]:
// MLIR: %[[#Ret_val:]] = llvm.load %[[#Ret_val_addr]] {alignment = 4 : i64} : !llvm.ptr -> i32
// MLIR: llvm.return %[[#Ret_val]] : i32
// MLIR: ^bb[[#GOTO_BLK]]:
// MLIR: %[[#Neg_one:]] = llvm.sub %[[#Zero]], %[[#One]] : i32
// MLIR: llvm.store %[[#Neg_one]], %[[#Ret_val_addr]] {{.*}}: i32, !llvm.ptr
// MLIR: llvm.br ^bb[[#RETURN]]
// MLIR: }
}

View File

@ -327,7 +327,6 @@ __m256i test_mm256_cvtepi8_epi16(__m128i a) {
// CHECK: sext <16 x i8> %{{.*}} to <16 x i16>
return _mm256_cvtepi8_epi16(a);
}
TEST_CONSTEXPR(match_v16hi(_mm256_cvtepi8_epi16(_mm_setr_epi8(-3, 2, -1, 0, 1, -2, 3, -4, 5, -6, 7, -8, 9, -10, 11, -12)), -3, 2, -1, 0, 1, -2, 3, -4, 5, -6, 7, -8, 9, -10, 11, -12));
__m256i test_mm256_cvtepi8_epi32(__m128i a) {
@ -336,7 +335,6 @@ __m256i test_mm256_cvtepi8_epi32(__m128i a) {
// CHECK: sext <8 x i8> %{{.*}} to <8 x i32>
return _mm256_cvtepi8_epi32(a);
}
TEST_CONSTEXPR(match_v8si(_mm256_cvtepi8_epi32(_mm_setr_epi8(-3, 2, -1, 0, 1, -2, 3, -4, 5, -6, 7, -8, 9, -10, 11, -12)), -3, 2, -1, 0, 1, -2, 3, -4));
__m256i test_mm256_cvtepi8_epi64(__m128i a) {
@ -345,7 +343,6 @@ __m256i test_mm256_cvtepi8_epi64(__m128i a) {
// CHECK: sext <4 x i8> %{{.*}} to <4 x i64>
return _mm256_cvtepi8_epi64(a);
}
TEST_CONSTEXPR(match_v4di(_mm256_cvtepi8_epi64(_mm_setr_epi8(-3, 2, -1, 0, 1, -2, 3, -4, 5, -6, 7, -8, 9, -10, 11, -12)), -3, 2, -1, 0));
__m256i test_mm256_cvtepi16_epi32(__m128i a) {
@ -353,7 +350,6 @@ __m256i test_mm256_cvtepi16_epi32(__m128i a) {
// CHECK: sext <8 x i16> %{{.*}} to <8 x i32>
return _mm256_cvtepi16_epi32(a);
}
TEST_CONSTEXPR(match_v8si(_mm256_cvtepi16_epi32(_mm_setr_epi16(-300, 2, -1, 0, 1, -2, 3, -4)), -300, 2, -1, 0, 1, -2, 3, -4));
__m256i test_mm256_cvtepi16_epi64(__m128i a) {
@ -362,7 +358,6 @@ __m256i test_mm256_cvtepi16_epi64(__m128i a) {
// CHECK: sext <4 x i16> %{{.*}} to <4 x i64>
return _mm256_cvtepi16_epi64(a);
}
TEST_CONSTEXPR(match_v4di(_mm256_cvtepi16_epi64(_mm_setr_epi16(-300, 2, -1, 0, 1, -2, 3, -4)), -300, 2, -1, 0));
__m256i test_mm256_cvtepi32_epi64(__m128i a) {
@ -370,7 +365,6 @@ __m256i test_mm256_cvtepi32_epi64(__m128i a) {
// CHECK: sext <4 x i32> %{{.*}} to <4 x i64>
return _mm256_cvtepi32_epi64(a);
}
TEST_CONSTEXPR(match_v4di(_mm256_cvtepi32_epi64(_mm_setr_epi32(-70000, 2, -1, 0)), -70000, 2, -1, 0));
__m256i test_mm256_cvtepu8_epi16(__m128i a) {
@ -378,7 +372,6 @@ __m256i test_mm256_cvtepu8_epi16(__m128i a) {
// CHECK: zext <16 x i8> %{{.*}} to <16 x i16>
return _mm256_cvtepu8_epi16(a);
}
TEST_CONSTEXPR(match_v16hi(_mm256_cvtepu8_epi16(_mm_setr_epi8(-3, 2, -1, 0, 1, -2, 3, -4, 5, -6, 7, -8, 9, -10, 11, -12)), 253, 2, 255, 0, 1, 254, 3, 252, 5, 250, 7, 248, 9, 246, 11, 244));
__m256i test_mm256_cvtepu8_epi32(__m128i a) {
@ -387,7 +380,6 @@ __m256i test_mm256_cvtepu8_epi32(__m128i a) {
// CHECK: zext <8 x i8> %{{.*}} to <8 x i32>
return _mm256_cvtepu8_epi32(a);
}
TEST_CONSTEXPR(match_v8si(_mm256_cvtepu8_epi32(_mm_setr_epi8(-3, 2, -1, 0, 1, -2, 3, -4, 5, -6, 7, -8, 9, -10, 11, -12)), 253, 2, 255, 0, 1, 254, 3, 252));
__m256i test_mm256_cvtepu8_epi64(__m128i a) {
@ -396,7 +388,6 @@ __m256i test_mm256_cvtepu8_epi64(__m128i a) {
// CHECK: zext <4 x i8> %{{.*}} to <4 x i64>
return _mm256_cvtepu8_epi64(a);
}
TEST_CONSTEXPR(match_v4di(_mm256_cvtepu8_epi64(_mm_setr_epi8(-3, 2, -1, 0, 1, -2, 3, -4, 5, -6, 7, -8, 9, -10, 11, -12)), 253, 2, 255, 0));
__m256i test_mm256_cvtepu16_epi32(__m128i a) {
@ -404,7 +395,6 @@ __m256i test_mm256_cvtepu16_epi32(__m128i a) {
// CHECK: zext <8 x i16> {{.*}} to <8 x i32>
return _mm256_cvtepu16_epi32(a);
}
TEST_CONSTEXPR(match_v8si(_mm256_cvtepu16_epi32(_mm_setr_epi16(-300, 2, -1, 0, 1, -2, 3, -4)), 65236, 2, 65535, 0, 1, 65534, 3, 65532));
__m256i test_mm256_cvtepu16_epi64(__m128i a) {
@ -413,7 +403,6 @@ __m256i test_mm256_cvtepu16_epi64(__m128i a) {
// CHECK: zext <4 x i16> %{{.*}} to <4 x i64>
return _mm256_cvtepu16_epi64(a);
}
TEST_CONSTEXPR(match_v4di(_mm256_cvtepu16_epi64(_mm_setr_epi16(-300, 2, -1, 0, 1, -2, 3, -4)), 65236, 2, 65535, 0));
__m256i test_mm256_cvtepu32_epi64(__m128i a) {
@ -421,7 +410,6 @@ __m256i test_mm256_cvtepu32_epi64(__m128i a) {
// CHECK: zext <4 x i32> %{{.*}} to <4 x i64>
return _mm256_cvtepu32_epi64(a);
}
TEST_CONSTEXPR(match_v4di(_mm256_cvtepu32_epi64(_mm_setr_epi32(-70000, 2, -1, 0)), 4294897296, 2, 4294967295, 0));
__m128i test0_mm256_extracti128_si256_0(__m256i a) {
@ -1120,24 +1108,28 @@ __m128i test_mm_sllv_epi32(__m128i a, __m128i b) {
// CHECK: call <4 x i32> @llvm.x86.avx2.psllv.d(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
return _mm_sllv_epi32(a, b);
}
TEST_CONSTEXPR(match_v4si(_mm_sllv_epi32((__m128i)(__v4si){1, -2, 3, -4}, (__m128i)(__v4si){1, 2, 3, -4}), 2, -8, 24, 0));
__m256i test_mm256_sllv_epi32(__m256i a, __m256i b) {
// CHECK-LABEL: test_mm256_sllv_epi32
// CHECK: call <8 x i32> @llvm.x86.avx2.psllv.d.256(<8 x i32> %{{.*}}, <8 x i32> %{{.*}})
return _mm256_sllv_epi32(a, b);
}
TEST_CONSTEXPR(match_v8si(_mm256_sllv_epi32((__m256i)(__v8si){1, -2, 3, -4, 5, -6, 7, -8}, (__m256i)(__v8si){1, 2, 3, 4, -17, 31, 33, 29}), 2, -8, 24, -64, 0, 0, 0, 0));
__m128i test_mm_sllv_epi64(__m128i a, __m128i b) {
// CHECK-LABEL: test_mm_sllv_epi64
// CHECK: call {{.*}}<2 x i64> @llvm.x86.avx2.psllv.q(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
return _mm_sllv_epi64(a, b);
}
TEST_CONSTEXPR(match_m128i(_mm_sllv_epi64((__m128i)(__v2di){1, -3}, (__m128i)(__v2di){8, 63}), 256, 0x8000000000000000ULL));
__m256i test_mm256_sllv_epi64(__m256i a, __m256i b) {
// CHECK-LABEL: test_mm256_sllv_epi64
// CHECK: call {{.*}}<4 x i64> @llvm.x86.avx2.psllv.q.256(<4 x i64> %{{.*}}, <4 x i64> %{{.*}})
return _mm256_sllv_epi64(a, b);
}
TEST_CONSTEXPR(match_m256i(_mm256_sllv_epi64((__m256i)(__v4di){1, -2, 3, -4}, (__m256i)(__v4di){1, 2, 3, -4}), 2, -8, 24, 0));
__m256i test_mm256_sra_epi16(__m256i a, __m128i b) {
// CHECK-LABEL: test_mm256_sra_epi16
@ -1180,12 +1172,14 @@ __m128i test_mm_srav_epi32(__m128i a, __m128i b) {
// CHECK: call <4 x i32> @llvm.x86.avx2.psrav.d(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
return _mm_srav_epi32(a, b);
}
TEST_CONSTEXPR(match_v4si(_mm_srav_epi32((__m128i)(__v4si){1, -2, 3, -4}, (__m128i)(__v4si){1, 2, 3, -4}), 0, -1, 0, -1));
__m256i test_mm256_srav_epi32(__m256i a, __m256i b) {
// CHECK-LABEL: test_mm256_srav_epi32
// CHECK: call <8 x i32> @llvm.x86.avx2.psrav.d.256(<8 x i32> %{{.*}}, <8 x i32> %{{.*}})
return _mm256_srav_epi32(a, b);
}
TEST_CONSTEXPR(match_v8si(_mm256_srav_epi32((__m256i)(__v8si){1, -2, 3, -4, 5, -6, 7, -8}, (__m256i)(__v8si){1, 2, 3, 4, -17, 31, 33, 29}), 0, -1, 0, -1, 0, -1, 0, -1));
__m256i test_mm256_srl_epi16(__m256i a, __m128i b) {
// CHECK-LABEL: test_mm256_srl_epi16
@ -1252,24 +1246,28 @@ __m128i test_mm_srlv_epi32(__m128i a, __m128i b) {
// CHECK: call <4 x i32> @llvm.x86.avx2.psrlv.d(<4 x i32> %{{.*}}, <4 x i32> %{{.*}})
return _mm_srlv_epi32(a, b);
}
TEST_CONSTEXPR(match_v4si(_mm_srlv_epi32((__m128i)(__v4si){1, -2, 3, -4}, (__m128i)(__v4si){1, 2, 3, -4}), 0, 1073741823, 0, 0));
__m256i test_mm256_srlv_epi32(__m256i a, __m256i b) {
// CHECK-LABEL: test_mm256_srlv_epi32
// CHECK: call <8 x i32> @llvm.x86.avx2.psrlv.d.256(<8 x i32> %{{.*}}, <8 x i32> %{{.*}})
return _mm256_srlv_epi32(a, b);
}
TEST_CONSTEXPR(match_v8si(_mm256_srlv_epi32((__m256i)(__v8si){1, -2, 3, -4, 5, -6, 7, -8}, (__m256i)(__v8si){1, 2, 3, 4, -17, 31, 33, 29}), 0, 1073741823, 0, 268435455, 0, 1, 0, 7));
__m128i test_mm_srlv_epi64(__m128i a, __m128i b) {
// CHECK-LABEL: test_mm_srlv_epi64
// CHECK: call {{.*}}<2 x i64> @llvm.x86.avx2.psrlv.q(<2 x i64> %{{.*}}, <2 x i64> %{{.*}})
return _mm_srlv_epi64(a, b);
}
TEST_CONSTEXPR(match_m128i(_mm_srlv_epi64((__m128i)(__v2di){1, -3}, (__m128i)(__v2di){8, 63}), 0, 1));
__m256i test_mm256_srlv_epi64(__m256i a, __m256i b) {
// CHECK-LABEL: test_mm256_srlv_epi64
// CHECK: call {{.*}}<4 x i64> @llvm.x86.avx2.psrlv.q.256(<4 x i64> %{{.*}}, <4 x i64> %{{.*}})
return _mm256_srlv_epi64(a, b);
}
TEST_CONSTEXPR(match_m256i(_mm256_srlv_epi64((__m256i)(__v4di){1, -2, 3, -4}, (__m256i)(__v4di){1, 2, 3, -4}), 0, 0x3FFFFFFFFFFFFFFFULL, 0, 0));
__m256i test_mm256_stream_load_si256(__m256i const *a) {
// CHECK-LABEL: test_mm256_stream_load_si256

View File

@ -3,6 +3,11 @@
// RUN: %clang_cc1 -x c++ -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +avx512f -emit-llvm -o - -Wall -Werror -Wsign-conversion | FileCheck %s
// RUN: %clang_cc1 -x c++ -flax-vector-conversions=none -fms-extensions -fms-compatibility -ffreestanding %s -triple=x86_64-windows-msvc -target-feature +avx512f -emit-llvm -o - -Wall -Werror -Wsign-conversion | FileCheck %s
// RUN: %clang_cc1 -x c -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +avx512f -emit-llvm -o - -Wall -Werror -Wsign-conversion -fexperimental-new-constant-interpreter | FileCheck %s
// RUN: %clang_cc1 -x c -flax-vector-conversions=none -fms-extensions -fms-compatibility -ffreestanding %s -triple=x86_64-windows-msvc -target-feature +avx512f -emit-llvm -o - -Wall -Werror -Wsign-conversion -fexperimental-new-constant-interpreter | FileCheck %s
// RUN: %clang_cc1 -x c++ -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +avx512f -emit-llvm -o - -Wall -Werror -Wsign-conversion -fexperimental-new-constant-interpreter | FileCheck %s
// RUN: %clang_cc1 -x c++ -flax-vector-conversions=none -fms-extensions -fms-compatibility -ffreestanding %s -triple=x86_64-windows-msvc -target-feature +avx512f -emit-llvm -o - -Wall -Werror -Wsign-conversion -fexperimental-new-constant-interpreter | FileCheck %s
#include <immintrin.h>
#include "builtin_test_helpers.h"

View File

@ -0,0 +1,12 @@
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -debug-info-kind=standalone -o - %s | FileCheck %s
template <typename T = int>
struct Y {
typedef int outside;
outside o;
};
Y<> y;
// CHECK: ![[Y:.*]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Y<int>", {{.*}}identifier: "_ZTS1YIiE")
// CHECK: !DIDerivedType(tag: DW_TAG_typedef, name: "outside", scope: ![[Y]],

Some files were not shown because too many files have changed in this diff Show More