Compare commits

...

51 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
283 changed files with 32662 additions and 3899 deletions

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

@ -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

@ -309,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

@ -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

@ -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

@ -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

@ -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

@ -1622,6 +1622,14 @@
// RUN: %clang_cc1 -x c -std=c99 -E -dM -ffreestanding -triple=amd64-unknown-openbsd < /dev/null | FileCheck -match-full-lines -check-prefix OPENBSD-STDC-N %s
// OPENBSD-STDC-N-NOT:#define __STDC_NO_THREADS__ 1
//
// RUN: %clang_cc1 -x c -std=c11 -E -dM -ffreestanding -triple=x86_64-unknown-dragonfly < /dev/null | FileCheck -match-full-lines -check-prefix DRAGONFLY-STDC %s
// RUN: %clang_cc1 -x c -std=gnu11 -E -dM -ffreestanding -triple=x86_64-unknown-dragonfly < /dev/null | FileCheck -match-full-lines -check-prefix DRAGONFLY-STDC %s
// RUN: %clang_cc1 -x c -std=c17 -E -dM -ffreestanding -triple=x86_64-unknown-dragonfly < /dev/null | FileCheck -match-full-lines -check-prefix DRAGONFLY-STDC %s
// DRAGONFLY-STDC:#define __STDC_NO_THREADS__ 1
//
// RUN: %clang_cc1 -x c -std=c99 -E -dM -ffreestanding -triple=x86_64-unknown-dragonfly < /dev/null | FileCheck -match-full-lines -check-prefix DRAGONFLY-STDC-N %s
// DRAGONFLY-STDC-N-NOT:#define __STDC_NO_THREADS__ 1
//
// RUN: %clang_cc1 -triple=aarch64-unknown-managarm-mlibc -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix MANAGARM %s
// RUN: %clang_cc1 -triple=riscv64-unknown-managarm-mlibc -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix MANAGARM %s
// RUN: %clang_cc1 -triple=x86_64-unknown-managarm-mlibc -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix MANAGARM %s

View File

@ -106,6 +106,12 @@ if(MSVC)
endif()
set(ASAN_CFLAGS ${SANITIZER_COMMON_CFLAGS})
# Win/ASan relies on the runtime functions being hotpatchable. See
# https://github.com/llvm/llvm-project/pull/149444
if(MSVC)
list(APPEND ASAN_CFLAGS /hotpatch)
endif()
append_list_if(MSVC /Zl ASAN_CFLAGS)
set(ASAN_COMMON_DEFINITIONS "")

View File

@ -2917,10 +2917,11 @@ mlir::Value IntrinsicLibrary::genAtand(mlir::Type resultType,
mlir::FunctionType::get(context, {resultType}, {args[0].getType()});
atan = getRuntimeCallGenerator("atan", ftype)(builder, loc, args);
}
llvm::APFloat pi = llvm::APFloat(llvm::numbers::pi);
mlir::Value dfactor = builder.createRealConstant(
loc, mlir::Float64Type::get(context), llvm::APFloat(180.0) / pi);
mlir::Value factor = builder.createConvert(loc, resultType, dfactor);
const llvm::fltSemantics &fltSem =
llvm::cast<mlir::FloatType>(resultType).getFloatSemantics();
llvm::APFloat pi = llvm::APFloat(fltSem, llvm::numbers::pis);
mlir::Value factor = builder.createRealConstant(
loc, resultType, llvm::APFloat(fltSem, "180.0") / pi);
return mlir::arith::MulFOp::create(builder, loc, atan, factor);
}

View File

@ -1,21 +1,19 @@
! RUN: bbc -emit-fir -hlfir=false %s -o - | FileCheck %s --check-prefixes="CHECK,CHECK-FAST"
! RUN: %flang_fc1 -emit-fir -flang-deprecated-no-hlfir %s -o - | FileCheck %s --check-prefixes="CHECK,CHECK-FAST"
function test_real4(y,x)
function test_real4(y, x)
real(4) :: x, y, test_real4
test_real4 = atan2d(y,x)
test_real4 = atan2d(y, x)
end function
! CHECK-LABEL: @_QPtest_real4
! CHECK-FAST: %[[atan2:.*]] = math.atan2 %{{.*}}, %{{.*}}: f32
! CHECK: %[[dfactor:.*]] = arith.constant 57.295779513082323 : f64
! CHECK: %[[factor:.*]] = fir.convert %[[dfactor]] : (f64) -> f32
! CHECK: %[[factor:.*]] = arith.constant 57.2957763 : f32
! CHECK: %{{.*}} = arith.mulf %[[atan2]], %[[factor]] fastmath<contract> : f32
function test_real8(y,x)
function test_real8(y, x)
real(8) :: x, y, test_real8
test_real8 = atan2d(y,x)
test_real8 = atan2d(y, x)
end function
! CHECK-LABEL: @_QPtest_real8

View File

@ -1,3 +1,4 @@
! REQUIRES: flang-supports-f128-math
! RUN: bbc -emit-fir -hlfir=false %s -o - | FileCheck %s --check-prefixes="CHECK,CHECK-FAST"
! RUN: bbc --math-runtime=precise -emit-fir -hlfir=false %s -o - | FileCheck %s --check-prefixes="CHECK,CHECK-PRECISE"
! RUN: %flang_fc1 -emit-fir -flang-deprecated-no-hlfir %s -o - | FileCheck %s --check-prefixes="CHECK,CHECK-FAST"
@ -10,8 +11,7 @@ end function
! CHECK-LABEL: @_QPtest_real4
! CHECK-PRECISE: %[[atan:.*]] = fir.call @atanf({{%[A-Za-z0-9._]+}}) fastmath<contract> : (f32) -> f32
! CHECK-FAST: %[[atan:.*]] = math.atan %{{.*}} : f32
! CHECK: %[[dfactor:.*]] = arith.constant 57.295779513082323 : f64
! CHECK: %[[factor:.*]] = fir.convert %[[dfactor]] : (f64) -> f32
! CHECK: %[[factor:.*]] = arith.constant 57.2957763 : f32
! CHECK: %{{.*}} = arith.mulf %[[atan]], %[[factor]] fastmath<contract> : f32
function test_real8(x)
@ -25,23 +25,42 @@ end function
! CHECK: %[[factor:.*]] = arith.constant 57.295779513082323 : f64
! CHECK: %{{.*}} = arith.mulf %[[atan]], %[[factor]] fastmath<contract> : f64
function test_real4_yx(y,x)
function test_real16(x)
real(16) :: x, test_real16
test_real16 = atand(x)
end function
! CHECK-LABEL: @_QPtest_real16
! CHECK: %[[atan:.*]] = fir.call @_FortranAAtanF128({{.*}}) fastmath<contract> : (f128) -> f128
! CHECK: %[[factor:.*]] = arith.constant 57.295779513082320876798154814105{{.*}} : f128
! CHECK: %{{.*}} = arith.mulf %[[atan]], %[[factor]] fastmath<contract> : f128
function test_real4_yx(y, x)
real(4) :: x, y, test_real4
test_real4 = atand(y,x)
test_real4 = atand(y, x)
end function
! CHECK-LABEL: @_QPtest_real4_yx
! CHECK: %[[atan2:.*]] = math.atan2 %{{.*}}, %{{.*}}: f32
! CHECK: %[[dfactor:.*]] = arith.constant 57.295779513082323 : f64
! CHECK: %[[factor:.*]] = fir.convert %[[dfactor]] : (f64) -> f32
! CHECK: %[[factor:.*]] = arith.constant 57.2957763 : f32
! CHECK: %{{.*}} = arith.mulf %[[atan2]], %[[factor]] fastmath<contract> : f32
function test_real8_yx(y,x)
function test_real8_yx(y, x)
real(8) :: x, y, test_real8
test_real8 = atand(y,x)
test_real8 = atand(y, x)
end function
! CHECK-LABEL: @_QPtest_real8_yx
! CHECK: %[[atan2:.*]] = math.atan2 %{{.*}}, %{{.*}}: f64
! CHECK: %[[factor:.*]] = arith.constant 57.295779513082323 : f64
! CHECK: %{{.*}} = arith.mulf %[[atan2]], %[[factor]] fastmath<contract> : f64
function test_real16_yx(y, x)
real(16) :: x, y, test_real16
test_real16 = atand(y, x)
end function
! CHECK-LABEL: @_QPtest_real16_yx
! CHECK: %[[atan2:.*]] = math.atan2 %{{.*}}, %{{.*}}: f128
! CHECK: %[[factor:.*]] = arith.constant 57.295779513082320876798154814105{{.*}} : f128
! CHECK: %{{.*}} = arith.mulf %[[atan]], %[[factor]] fastmath<contract> : f128

View File

@ -280,6 +280,7 @@ set(TARGET_LIBC_ENTRYPOINTS
set(TARGET_LIBM_ENTRYPOINTS
# math.h entrypoints
libc.src.math.acos
libc.src.math.acosf
libc.src.math.acoshf
libc.src.math.asin

View File

@ -2432,14 +2432,6 @@ functions:
return_type: double
arguments:
- type: double
- name: sincosf
standards:
- gnu
return_type: void
arguments:
- type: float
- type: float *
- type: float *
- name: sinf
standards:
- stdc
@ -2453,6 +2445,22 @@ functions:
arguments:
- type: _Float16
guard: LIBC_TYPES_HAS_FLOAT16
- name: sincos
standards:
- gnu
return_type: void
arguments:
- type: double
- type: double *
- type: double *
- name: sincosf
standards:
- gnu
return_type: void
arguments:
- type: float
- type: float *
- type: float *
- name: sinhf
standards:
- stdc

View File

@ -978,11 +978,11 @@ public:
# ifndef _LIBCPP_CXX03_LANG
_LIBCPP_HIDE_FROM_ABI map(map&& __m) noexcept(is_nothrow_move_constructible<__base>::value) = default;
_LIBCPP_HIDE_FROM_ABI map(map&& __m) = default;
_LIBCPP_HIDE_FROM_ABI map(map&& __m, const allocator_type& __a);
_LIBCPP_HIDE_FROM_ABI map& operator=(map&& __m) noexcept(is_nothrow_move_assignable<__base>::value) = default;
_LIBCPP_HIDE_FROM_ABI map& operator=(map&& __m) = default;
_LIBCPP_HIDE_FROM_ABI map(initializer_list<value_type> __il, const key_compare& __comp = key_compare())
: __tree_(__vc(__comp)) {
@ -1646,12 +1646,11 @@ public:
# ifndef _LIBCPP_CXX03_LANG
_LIBCPP_HIDE_FROM_ABI multimap(multimap&& __m) noexcept(is_nothrow_move_constructible<__base>::value) = default;
_LIBCPP_HIDE_FROM_ABI multimap(multimap&& __m) = default;
_LIBCPP_HIDE_FROM_ABI multimap(multimap&& __m, const allocator_type& __a);
_LIBCPP_HIDE_FROM_ABI multimap&
operator=(multimap&& __m) noexcept(is_nothrow_move_assignable<__base>::value) = default;
_LIBCPP_HIDE_FROM_ABI multimap& operator=(multimap&& __m) = default;
_LIBCPP_HIDE_FROM_ABI multimap(initializer_list<value_type> __il, const key_compare& __comp = key_compare())
: __tree_(__vc(__comp)) {

View File

@ -667,7 +667,7 @@ public:
_LIBCPP_HIDE_FROM_ABI set& operator=(const set& __s) = default;
# ifndef _LIBCPP_CXX03_LANG
_LIBCPP_HIDE_FROM_ABI set(set&& __s) noexcept(is_nothrow_move_constructible<__base>::value) = default;
_LIBCPP_HIDE_FROM_ABI set(set&& __s) = default;
# endif // _LIBCPP_CXX03_LANG
_LIBCPP_HIDE_FROM_ABI explicit set(const allocator_type& __a) : __tree_(__a) {}
@ -699,10 +699,7 @@ public:
return *this;
}
_LIBCPP_HIDE_FROM_ABI set& operator=(set&& __s) noexcept(is_nothrow_move_assignable<__base>::value) {
__tree_ = std::move(__s.__tree_);
return *this;
}
_LIBCPP_HIDE_FROM_ABI set& operator=(set&& __s) = default;
# endif // _LIBCPP_CXX03_LANG
_LIBCPP_HIDE_FROM_ABI ~set() { static_assert(sizeof(std::__diagnose_non_const_comparator<_Key, _Compare>()), ""); }
@ -1126,7 +1123,7 @@ public:
_LIBCPP_HIDE_FROM_ABI multiset& operator=(const multiset& __s) = default;
# ifndef _LIBCPP_CXX03_LANG
_LIBCPP_HIDE_FROM_ABI multiset(multiset&& __s) noexcept(is_nothrow_move_constructible<__base>::value) = default;
_LIBCPP_HIDE_FROM_ABI multiset(multiset&& __s) = default;
_LIBCPP_HIDE_FROM_ABI multiset(multiset&& __s, const allocator_type& __a);
# endif // _LIBCPP_CXX03_LANG
@ -1158,10 +1155,7 @@ public:
return *this;
}
_LIBCPP_HIDE_FROM_ABI multiset& operator=(multiset&& __s) _NOEXCEPT_(is_nothrow_move_assignable<__base>::value) {
__tree_ = std::move(__s.__tree_);
return *this;
}
_LIBCPP_HIDE_FROM_ABI multiset& operator=(multiset&& __s) = default;
# endif // _LIBCPP_CXX03_LANG
_LIBCPP_HIDE_FROM_ABI ~multiset() {

View File

@ -1049,8 +1049,7 @@ public:
_LIBCPP_HIDE_FROM_ABI unordered_map(const unordered_map& __u) = default;
_LIBCPP_HIDE_FROM_ABI unordered_map(const unordered_map& __u, const allocator_type& __a);
# ifndef _LIBCPP_CXX03_LANG
_LIBCPP_HIDE_FROM_ABI unordered_map(unordered_map&& __u)
_NOEXCEPT_(is_nothrow_move_constructible<__table>::value) = default;
_LIBCPP_HIDE_FROM_ABI unordered_map(unordered_map&& __u) = default;
_LIBCPP_HIDE_FROM_ABI unordered_map(unordered_map&& __u, const allocator_type& __a);
_LIBCPP_HIDE_FROM_ABI unordered_map(initializer_list<value_type> __il);
_LIBCPP_HIDE_FROM_ABI
@ -1102,8 +1101,7 @@ public:
_LIBCPP_HIDE_FROM_ABI unordered_map& operator=(const unordered_map& __u) = default;
# ifndef _LIBCPP_CXX03_LANG
_LIBCPP_HIDE_FROM_ABI unordered_map& operator=(unordered_map&& __u)
_NOEXCEPT_(is_nothrow_move_assignable<__table>::value) = default;
_LIBCPP_HIDE_FROM_ABI unordered_map& operator=(unordered_map&& __u) = default;
_LIBCPP_HIDE_FROM_ABI unordered_map& operator=(initializer_list<value_type> __il);
# endif // _LIBCPP_CXX03_LANG
@ -1823,8 +1821,7 @@ public:
_LIBCPP_HIDE_FROM_ABI unordered_multimap(const unordered_multimap& __u) = default;
_LIBCPP_HIDE_FROM_ABI unordered_multimap(const unordered_multimap& __u, const allocator_type& __a);
# ifndef _LIBCPP_CXX03_LANG
_LIBCPP_HIDE_FROM_ABI unordered_multimap(unordered_multimap&& __u)
_NOEXCEPT_(is_nothrow_move_constructible<__table>::value) = default;
_LIBCPP_HIDE_FROM_ABI unordered_multimap(unordered_multimap&& __u) = default;
_LIBCPP_HIDE_FROM_ABI unordered_multimap(unordered_multimap&& __u, const allocator_type& __a);
_LIBCPP_HIDE_FROM_ABI unordered_multimap(initializer_list<value_type> __il);
_LIBCPP_HIDE_FROM_ABI unordered_multimap(
@ -1876,8 +1873,7 @@ public:
_LIBCPP_HIDE_FROM_ABI unordered_multimap& operator=(const unordered_multimap& __u) = default;
# ifndef _LIBCPP_CXX03_LANG
_LIBCPP_HIDE_FROM_ABI unordered_multimap& operator=(unordered_multimap&& __u)
_NOEXCEPT_(is_nothrow_move_assignable<__table>::value) = default;
_LIBCPP_HIDE_FROM_ABI unordered_multimap& operator=(unordered_multimap&& __u) = default;
_LIBCPP_HIDE_FROM_ABI unordered_multimap& operator=(initializer_list<value_type> __il);
# endif // _LIBCPP_CXX03_LANG

View File

@ -706,7 +706,7 @@ public:
_LIBCPP_HIDE_FROM_ABI unordered_set(const unordered_set& __u) = default;
_LIBCPP_HIDE_FROM_ABI unordered_set(const unordered_set& __u, const allocator_type& __a);
# ifndef _LIBCPP_CXX03_LANG
_LIBCPP_HIDE_FROM_ABI unordered_set(unordered_set&& __u) _NOEXCEPT_(is_nothrow_move_constructible<__table>::value);
_LIBCPP_HIDE_FROM_ABI unordered_set(unordered_set&& __u) = default;
_LIBCPP_HIDE_FROM_ABI unordered_set(unordered_set&& __u, const allocator_type& __a);
_LIBCPP_HIDE_FROM_ABI unordered_set(initializer_list<value_type> __il);
_LIBCPP_HIDE_FROM_ABI
@ -735,8 +735,7 @@ public:
_LIBCPP_HIDE_FROM_ABI unordered_set& operator=(const unordered_set& __u) = default;
# ifndef _LIBCPP_CXX03_LANG
_LIBCPP_HIDE_FROM_ABI unordered_set& operator=(unordered_set&& __u)
_NOEXCEPT_(is_nothrow_move_assignable<__table>::value) = default;
_LIBCPP_HIDE_FROM_ABI unordered_set& operator=(unordered_set&& __u) = default;
_LIBCPP_HIDE_FROM_ABI unordered_set& operator=(initializer_list<value_type> __il);
# endif // _LIBCPP_CXX03_LANG
@ -1076,11 +1075,6 @@ unordered_set<_Value, _Hash, _Pred, _Alloc>::unordered_set(const unordered_set&
# ifndef _LIBCPP_CXX03_LANG
template <class _Value, class _Hash, class _Pred, class _Alloc>
inline unordered_set<_Value, _Hash, _Pred, _Alloc>::unordered_set(unordered_set&& __u)
_NOEXCEPT_(is_nothrow_move_constructible<__table>::value)
: __table_(std::move(__u.__table_)) {}
template <class _Value, class _Hash, class _Pred, class _Alloc>
unordered_set<_Value, _Hash, _Pred, _Alloc>::unordered_set(unordered_set&& __u, const allocator_type& __a)
: __table_(std::move(__u.__table_), __a) {
@ -1294,8 +1288,7 @@ public:
_LIBCPP_HIDE_FROM_ABI unordered_multiset(const unordered_multiset& __u) = default;
_LIBCPP_HIDE_FROM_ABI unordered_multiset(const unordered_multiset& __u, const allocator_type& __a);
# ifndef _LIBCPP_CXX03_LANG
_LIBCPP_HIDE_FROM_ABI unordered_multiset(unordered_multiset&& __u)
_NOEXCEPT_(is_nothrow_move_constructible<__table>::value);
_LIBCPP_HIDE_FROM_ABI unordered_multiset(unordered_multiset&& __u) = default;
_LIBCPP_HIDE_FROM_ABI unordered_multiset(unordered_multiset&& __u, const allocator_type& __a);
_LIBCPP_HIDE_FROM_ABI unordered_multiset(initializer_list<value_type> __il);
_LIBCPP_HIDE_FROM_ABI unordered_multiset(
@ -1324,8 +1317,7 @@ public:
_LIBCPP_HIDE_FROM_ABI unordered_multiset& operator=(const unordered_multiset& __u) = default;
# ifndef _LIBCPP_CXX03_LANG
_LIBCPP_HIDE_FROM_ABI unordered_multiset& operator=(unordered_multiset&& __u)
_NOEXCEPT_(is_nothrow_move_assignable<__table>::value) = default;
_LIBCPP_HIDE_FROM_ABI unordered_multiset& operator=(unordered_multiset&& __u) = default;
_LIBCPP_HIDE_FROM_ABI unordered_multiset& operator=(initializer_list<value_type> __il);
# endif // _LIBCPP_CXX03_LANG
@ -1675,11 +1667,6 @@ unordered_multiset<_Value, _Hash, _Pred, _Alloc>::unordered_multiset(
# ifndef _LIBCPP_CXX03_LANG
template <class _Value, class _Hash, class _Pred, class _Alloc>
inline unordered_multiset<_Value, _Hash, _Pred, _Alloc>::unordered_multiset(unordered_multiset&& __u)
_NOEXCEPT_(is_nothrow_move_constructible<__table>::value)
: __table_(std::move(__u.__table_)) {}
template <class _Value, class _Hash, class _Pred, class _Alloc>
unordered_multiset<_Value, _Hash, _Pred, _Alloc>::unordered_multiset(
unordered_multiset&& __u, const allocator_type& __a)

View File

@ -1399,6 +1399,7 @@ void SymbolTable::resolveAlternateNames() {
auto toUndef = dyn_cast<Undefined>(toSym);
if (toUndef && (!toUndef->weakAlias || toUndef->isAntiDep))
continue;
toSym->isUsedInRegularObj = true;
if (toSym->isLazy())
forceLazy(toSym);
u->setWeakAlias(toSym);

View File

@ -39,6 +39,7 @@ public:
void relocate(uint8_t *loc, const Relocation &rel,
uint64_t val) const override;
bool relaxOnce(int pass) const override;
bool synthesizeAlign(uint64_t &dot, InputSection *sec) override;
RelExpr adjustTlsExpr(RelType type, RelExpr expr) const override;
void relocateAlloc(InputSectionBase &sec, uint8_t *buf) const override;
void finalizeRelax(int passes) const override;
@ -48,6 +49,19 @@ private:
void tlsdescToLe(uint8_t *loc, const Relocation &rel, uint64_t val) const;
bool tryGotToPCRel(uint8_t *loc, const Relocation &rHi20,
const Relocation &rLo12, uint64_t secAddr) const;
template <class ELFT, class RelTy>
bool synthesizeAlignForInput(uint64_t &dot, InputSection *sec,
Relocs<RelTy> rels);
template <class ELFT, class RelTy>
void finalizeSynthesizeAligns(uint64_t &dot, InputSection *sec,
Relocs<RelTy> rels);
template <class ELFT>
bool synthesizeAlignAux(uint64_t &dot, InputSection *sec);
// The following two variables are used by synthesized ALIGN relocations.
InputSection *baseSec = nullptr;
// r_offset and r_addend pairs.
SmallVector<std::pair<uint64_t, uint64_t>, 0> synthesizedAligns;
};
} // end anonymous namespace
@ -766,6 +780,117 @@ void LoongArch::relocate(uint8_t *loc, const Relocation &rel,
}
}
// If the section alignment is > 4, advance `dot` to insert NOPs and synthesize
// an ALIGN relocation. Otherwise, return false to use default handling.
template <class ELFT, class RelTy>
bool LoongArch::synthesizeAlignForInput(uint64_t &dot, InputSection *sec,
Relocs<RelTy> rels) {
if (!baseSec) {
// Record the first input section with RELAX relocations. We will synthesize
// ALIGN relocations here.
for (auto rel : rels) {
if (rel.getType(false) == R_LARCH_RELAX) {
baseSec = sec;
break;
}
}
} else if (sec->addralign > 4) {
// If the alignment is > 4 and the section does not start with an ALIGN
// relocation, synthesize one.
bool hasAlignRel = llvm::any_of(rels, [](const RelTy &rel) {
return rel.r_offset == 0 && rel.getType(false) == R_LARCH_ALIGN;
});
if (!hasAlignRel) {
synthesizedAligns.emplace_back(dot - baseSec->getVA(),
sec->addralign - 4);
dot += sec->addralign - 4;
return true;
}
}
return false;
}
// Finalize the relocation section by appending synthesized ALIGN relocations
// after processing all input sections.
template <class ELFT, class RelTy>
void LoongArch::finalizeSynthesizeAligns(uint64_t &dot, InputSection *sec,
Relocs<RelTy> rels) {
auto *f = cast<ObjFile<ELFT>>(baseSec->file);
auto shdr = f->template getELFShdrs<ELFT>()[baseSec->relSecIdx];
// Create a copy of InputSection.
sec = make<InputSection>(*f, shdr, baseSec->name);
auto *baseRelSec = cast<InputSection>(f->getSections()[baseSec->relSecIdx]);
*sec = *baseRelSec;
baseSec = nullptr;
// Allocate buffer for original and synthesized relocations in RELA format.
// If CREL is used, OutputSection::finalizeNonAllocCrel will convert RELA to
// CREL.
auto newSize = rels.size() + synthesizedAligns.size();
auto *relas = makeThreadLocalN<typename ELFT::Rela>(newSize);
sec->size = newSize * sizeof(typename ELFT::Rela);
sec->content_ = reinterpret_cast<uint8_t *>(relas);
sec->type = SHT_RELA;
// Copy original relocations to the new buffer, potentially converting CREL to
// RELA.
for (auto [i, r] : llvm::enumerate(rels)) {
relas[i].r_offset = r.r_offset;
relas[i].setSymbolAndType(r.getSymbol(0), r.getType(0), false);
if constexpr (RelTy::HasAddend)
relas[i].r_addend = r.r_addend;
}
// Append synthesized ALIGN relocations to the buffer.
for (auto [i, r] : llvm::enumerate(synthesizedAligns)) {
auto &rela = relas[rels.size() + i];
rela.r_offset = r.first;
rela.setSymbolAndType(0, R_LARCH_ALIGN, false);
rela.r_addend = r.second;
}
synthesizedAligns.clear();
// Replace the old relocation section with the new one in the output section.
// addOrphanSections ensures that the output relocation section is processed
// after osec.
for (SectionCommand *cmd : sec->getParent()->commands) {
auto *isd = dyn_cast<InputSectionDescription>(cmd);
if (!isd)
continue;
for (auto *&isec : isd->sections)
if (isec == baseRelSec)
isec = sec;
}
}
template <class ELFT>
bool LoongArch::synthesizeAlignAux(uint64_t &dot, InputSection *sec) {
bool ret = false;
if (sec) {
invokeOnRelocs(*sec, ret = synthesizeAlignForInput<ELFT>, dot, sec);
} else if (baseSec) {
invokeOnRelocs(*baseSec, finalizeSynthesizeAligns<ELFT>, dot, sec);
}
return ret;
}
// Without linker relaxation enabled for a particular relocatable file or
// section, the assembler will not generate R_LARCH_ALIGN relocations for
// alignment directives. This becomes problematic in a two-stage linking
// process: ld -r a.o b.o -o ab.o; ld ab.o -o ab. This function synthesizes an
// R_LARCH_ALIGN relocation at section start when needed.
//
// When called with an input section (`sec` is not null): If the section
// alignment is > 4, advance `dot` to insert NOPs and synthesize an ALIGN
// relocation.
//
// When called after all input sections are processed (`sec` is null): The
// output relocation section is updated with all the newly synthesized ALIGN
// relocations.
bool LoongArch::synthesizeAlign(uint64_t &dot, InputSection *sec) {
assert(ctx.arg.relocatable);
if (ctx.arg.is64)
return synthesizeAlignAux<ELF64LE>(dot, sec);
return synthesizeAlignAux<ELF32LE>(dot, sec);
}
static bool relaxable(ArrayRef<Relocation> relocs, size_t i) {
return i + 1 < relocs.size() && relocs[i + 1].type == R_LARCH_RELAX;
}

View File

@ -1230,9 +1230,9 @@ bool LinkerScript::assignOffsets(OutputSection *sec) {
if (sec->firstInOverlay)
state->overlaySize = 0;
bool synthesizeAlign = ctx.arg.relocatable && ctx.arg.relax &&
(sec->flags & SHF_EXECINSTR) &&
ctx.arg.emachine == EM_RISCV;
bool synthesizeAlign =
ctx.arg.relocatable && ctx.arg.relax && (sec->flags & SHF_EXECINSTR) &&
(ctx.arg.emachine == EM_LOONGARCH || ctx.arg.emachine == EM_RISCV);
// We visited SectionsCommands from processSectionCommands to
// layout sections. Now, we visit SectionsCommands again to fix
// section offsets.

View File

@ -899,6 +899,8 @@ std::array<uint8_t, 4> OutputSection::getFiller(Ctx &ctx) {
return {1, 0, 1, 0};
return {0x13, 0, 0, 0};
}
if (ctx.arg.relocatable && ctx.arg.emachine == EM_LOONGARCH)
return {0, 0, 0x40, 0x03};
return ctx.target->trapInstr;
}

View File

@ -0,0 +1,25 @@
; REQUIRES: x86
; RUN: mkdir -p %t.dir
; RUN: llvm-as -o %t.obj %s
; RUN: lld-link -out:%t.dll -dll -noentry %t.obj -export:test
target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-windows-msvc19.33.0"
$alt = comdat any
@alt = weak_odr dso_local global i32 0, comdat, align 4
@ext = external dso_local global i32, align 4
; Function Attrs: noinline nounwind optnone uwtable
define dso_local i32 @test() #0 {
entry:
%0 = load i32, ptr @ext, align 4
ret i32 %0
}
attributes #0 = { noinline nounwind optnone uwtable }
!llvm.linker.options = !{!0}
!0 = !{!"/alternatename:ext=alt"}

View File

@ -0,0 +1,147 @@
# REQUIRES: loongarch
## Test LA64.
# RUN: rm -rf %t && split-file %s %t && cd %t
# RUN: llvm-mc -filetype=obj -triple=loongarch64 -mattr=+relax a.s -o a.o
# RUN: llvm-mc -filetype=obj -triple=loongarch64 -mattr=+relax --defsym ELF64=1 b.s -o b.o
# RUN: llvm-mc -filetype=obj -triple=loongarch64 -mattr=+relax b1.s -o b1.o
# RUN: llvm-mc -filetype=obj -triple=loongarch64 -mattr=+relax c.s -o c.o
# RUN: llvm-mc -filetype=obj -triple=loongarch64 d.s -o d.o
## No RELAX. Don't synthesize ALIGN.
# RUN: ld.lld -r b.o d.o -o bd.ro
# RUN: llvm-readelf -r bd.ro | FileCheck %s --check-prefix=NOREL
# NOREL: no relocations
# RUN: ld.lld -r b.o b.o a.o b.o b1.o c.o d.o -o out.ro
# RUN: llvm-objdump -dr --no-show-raw-insn out.ro | FileCheck %s
# RUN: llvm-readelf -r out.ro | FileCheck %s --check-prefix=CHECK-REL
# CHECK: <b0>:
# CHECK-NEXT: 0: addi.d $a0, $a1, 1
# CHECK-NEXT: 4: nop
# CHECK-EMPTY:
# CHECK-NEXT: <b0>:
# CHECK-NEXT: 8: addi.d $a0, $a1, 1
# CHECK-EMPTY:
# CHECK-NEXT: <_start>:
# CHECK-NEXT: c: pcalau12i $a0, 0
# CHECK-NEXT: 000000000000000c: R_LARCH_PCALA_HI20 .Ltext1_start
# CHECK-NEXT: 000000000000000c: R_LARCH_RELAX *ABS*
# CHECK-NEXT: 10: addi.d $a0, $a0, 0
# CHECK-NEXT: 0000000000000010: R_LARCH_PCALA_LO12 .Ltext1_start
# CHECK-NEXT: 0000000000000010: R_LARCH_RELAX *ABS*
# CHECK-NEXT: 14: nop
# CHECK-NEXT: 0000000000000014: R_LARCH_ALIGN *ABS*+0x4
# CHECK-EMPTY:
# CHECK-NEXT: <b0>:
# CHECK-NEXT: 18: addi.d $a0, $a1, 1
# CHECK-NEXT: 1c: nop
# CHECK-NEXT: 20: nop
# CHECK-NEXT: 0000000000000020: R_LARCH_ALIGN *ABS*+0x4
# CHECK-NEXT: 24: nop
# CHECK-EMPTY:
# CHECK-NEXT: <b1>:
# CHECK-NEXT: 28: addi.d $a0, $a1, 3
# CHECK-EMPTY:
# CHECK-NEXT: <c0>:
# CHECK-NEXT: 2c: addi.d $a0, $a1, 4
# CHECK-NEXT: 30: nop
# CHECK-NEXT: 0000000000000030: R_LARCH_ALIGN *ABS*+0x4
# CHECK-EMPTY:
# CHECK-NEXT: <d0>:
# CHECK-NEXT: 34: addi.d $a0, $a1, 5
# CHECK-REL: Relocation section '.rela.text' at offset {{.*}} contains 7 entries:
# CHECK-REL: Relocation section '.rela.text1' at offset {{.*}} contains 5 entries:
## Test LA32.
# RUN: llvm-mc -filetype=obj -triple=loongarch32 -mattr=+relax a.s -o a.32.o
# RUN: llvm-mc -filetype=obj -triple=loongarch32 -mattr=+relax b.s -o b.32.o
# RUN: ld.lld -r a.32.o b.32.o -o out.32.ro
# RUN: ld.lld -Ttext=0x10000 out.32.ro -o out32
# RUN: llvm-objdump -dr --no-show-raw-insn out32 | FileCheck %s --check-prefix=CHECK32
# CHECK32: <_start>:
# CHECK32-NEXT: 10000: pcaddi $a0, 4
# CHECK32-NEXT: 10004: nop
# CHECK32-EMPTY:
# CHECK32-NEXT: <b0>:
# CHECK32-NEXT: 10008: addi.w $a0, $a1, 1
# CHECK32: <.Ltext1_start>:
# CHECK32-NEXT: 10010: pcaddi $a1, 0
# CHECK32-NEXT: 10014: nop
# CHECK32-NEXT: 10018: addi.w $a0, $a1, 2
## Test CREL.
# RUN: llvm-mc -filetype=obj -triple=loongarch64 -mattr=+relax --crel a.s -o acrel.o
# RUN: ld.lld -r acrel.o b.o -o out.crel.ro
# RUN: llvm-objdump -dr --no-show-raw-insn out.crel.ro | FileCheck %s --check-prefix=CHECKC
# CHECKC: <_start>:
# CHECKC-NEXT: 0: pcalau12i $a0, 0
# CHECKC-NEXT: 0000000000000000: R_LARCH_PCALA_HI20 .Ltext1_start
# CHECKC-NEXT: 0000000000000000: R_LARCH_RELAX *ABS*
# CHECKC-NEXT: 4: addi.d $a0, $a0, 0
# CHECKC-NEXT: 0000000000000004: R_LARCH_PCALA_LO12 .Ltext1_start
# CHECKC-NEXT: 0000000000000004: R_LARCH_RELAX *ABS*
# CHECKC-NEXT: 8: nop
# CHECKC-NEXT: 0000000000000008: R_LARCH_ALIGN *ABS*+0x4
# CHECKC-EMPTY:
# CHECKC-NEXT: <b0>:
# CHECKC-NEXT: c: addi.d $a0, $a1, 1
#--- a.s
.globl _start
_start:
la.pcrel $a0, .Ltext1_start
.section .text1,"ax"
.Ltext1_start:
la.pcrel $a1, .Ltext1_start
#--- b.s
.macro addi dst, src1, src2
.ifdef ELF64
addi.d \dst, \src1, \src2
.else
addi.w \dst, \src1, \src2
.endif
.endm
## Needs synthesized ALIGN.
.option push
.option norelax
.balign 8
b0:
addi $a0, $a1, 1
.section .text1,"ax"
.balign 8
addi $a0, $a1, 2
.option pop
#--- b1.s
# Starts with an ALIGN relocation, don't need synthesized ALIGN.
.option push
.option norelax
.reloc ., R_LARCH_ALIGN, 4
nop
.balign 8
b1:
addi.d $a0, $a1, 3
.option pop
#--- c.s
## Alignment == 4, don't need synthesized ALIGN.
.balign 4
c0:
addi.d $a0, $a1, 4
#--- d.s
## Needs synthesized ALIGN.
.balign 8
d0:
addi.d $a0, $a1, 5

View File

@ -1540,13 +1540,19 @@ def load_crashlog_in_scripted_process(debugger, crashlog_path, options, result):
}
)
)
crashlog_sd = lldb.SBStructuredData()
crashlog_sd.SetGenericValue(
lldb.SBScriptObject(crashlog, lldb.eScriptLanguagePython)
)
structured_data.SetValueForKey("crashlog", crashlog_sd)
launch_info = lldb.SBLaunchInfo(None)
launch_info.SetProcessPluginName("ScriptedProcess")
launch_info.SetScriptedProcessClassName(
"crashlog_scripted_process.CrashLogScriptedProcess"
)
launch_info.SetScriptedProcessDictionary(structured_data)
launch_info.SetLaunchFlags(lldb.eLaunchFlagStopAtEntry)
error = lldb.SBError()
process = target.Launch(launch_info, error)
@ -1554,9 +1560,6 @@ def load_crashlog_in_scripted_process(debugger, crashlog_path, options, result):
if not process or error.Fail():
raise InteractiveCrashLogException("couldn't launch Scripted Process", error)
process.GetScriptedImplementation().set_crashlog(crashlog)
process.Continue()
if not options.skip_status:
@contextlib.contextmanager

View File

@ -10,8 +10,7 @@ from lldb.macosx.crashlog import CrashLog, CrashLogParser
class CrashLogScriptedProcess(ScriptedProcess):
def set_crashlog(self, crashlog):
self.crashlog = crashlog
def parse_crashlog(self):
if self.crashlog.process_id:
if type(self.crashlog.process_id) is int:
self.pid = self.crashlog.process_id
@ -29,8 +28,6 @@ class CrashLogScriptedProcess(ScriptedProcess):
if hasattr(self.crashlog, "asb"):
self.extended_thread_info = self.crashlog.asb
crashlog.load_images(self.options, self.loaded_images)
for thread in self.crashlog.threads:
if (
hasattr(thread, "app_specific_backtrace")
@ -92,10 +89,21 @@ class CrashLogScriptedProcess(ScriptedProcess):
no_parallel_image_loading.GetBooleanValue()
)
self.crashlog = None
crashlog = args.GetValueForKey("crashlog")
if crashlog and crashlog.IsValid():
if crashlog.GetType() == lldb.eStructuredDataTypeGeneric:
self.crashlog = crashlog.GetGenericValue()
if not self.crashlog:
# Return error
return
self.pid = super().get_process_id()
self.crashed_thread_idx = 0
self.exception = None
self.extended_thread_info = None
self.parse_crashlog()
def read_memory_at_address(
self, addr: int, size: int, error: lldb.SBError
@ -104,8 +112,8 @@ class CrashLogScriptedProcess(ScriptedProcess):
return lldb.SBData()
def get_loaded_images(self):
# TODO: Iterate over corefile_target modules and build a data structure
# from it.
if len(self.loaded_images) == 0:
self.crashlog.load_images(self.options, self.loaded_images)
return self.loaded_images
def should_stop(self) -> bool:

View File

@ -85,12 +85,6 @@ public:
SymbolType GetType();
/// Get the ID of this symbol, usually the original symbol table index.
///
/// \returns
/// Returns the ID of this symbol.
uint32_t GetID();
bool operator==(const lldb::SBSymbol &rhs) const;
bool operator!=(const lldb::SBSymbol &rhs) const;
@ -105,15 +99,6 @@ public:
// other than the actual symbol table itself in the object file.
bool IsSynthetic();
/// Returns true if the symbol is a debug symbol.
bool IsDebug();
/// Get the string representation of a symbol type.
static const char *GetTypeAsString(lldb::SymbolType symbol_type);
/// Get the symbol type from a string representation.
static lldb::SymbolType GetTypeFromString(const char *str);
protected:
lldb_private::Symbol *get();

View File

@ -324,16 +324,6 @@ public:
lldb::SBModule FindModule(const lldb::SBFileSpec &file_spec);
/// Find a module with the given module specification.
///
/// \param[in] module_spec
/// A lldb::SBModuleSpec object that contains module specification.
///
/// \return
/// A lldb::SBModule object that represents the found module, or an
/// invalid SBModule object if no module was found.
lldb::SBModule FindModule(const lldb::SBModuleSpec &module_spec);
/// Find compile units related to *this target and passed source
/// file.
///

View File

@ -15,7 +15,6 @@
#include "lldb/Symbol/SymbolContextScope.h"
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/UserID.h"
#include "lldb/lldb-enumerations.h"
#include "lldb/lldb-private.h"
#include "llvm/Support/JSON.h"
@ -302,10 +301,6 @@ public:
bool operator==(const Symbol &rhs) const;
static const char *GetTypeAsString(lldb::SymbolType symbol_type);
static lldb::SymbolType GetTypeFromString(const char *str);
protected:
// This is the internal guts of ResolveReExportedSymbol, it assumes
// reexport_name is not null, and that module_spec is valid. We track the

View File

@ -1299,25 +1299,6 @@ class DebugCommunication(object):
{"command": "modules", "type": "request", "arguments": args_dict}
)
def request_moduleSymbols(
self,
moduleId: str = "",
moduleName: str = "",
startIndex: int = 0,
count: int = 0,
):
command_dict = {
"command": "__lldb_moduleSymbols",
"type": "request",
"arguments": {
"moduleId": moduleId,
"moduleName": moduleName,
"startIndex": startIndex,
"count": count,
},
}
return self._send_recv(command_dict)
def request_stackTrace(
self, threadId=None, startFrame=None, levels=None, format=None, dump=False
):

View File

@ -193,14 +193,6 @@ SymbolType SBSymbol::GetType() {
return eSymbolTypeInvalid;
}
uint32_t SBSymbol::GetID() {
LLDB_INSTRUMENT_VA(this);
if (m_opaque_ptr)
return m_opaque_ptr->GetID();
return 0;
}
bool SBSymbol::IsExternal() {
LLDB_INSTRUMENT_VA(this);
@ -216,23 +208,3 @@ bool SBSymbol::IsSynthetic() {
return m_opaque_ptr->IsSynthetic();
return false;
}
bool SBSymbol::IsDebug() {
LLDB_INSTRUMENT_VA(this);
if (m_opaque_ptr)
return m_opaque_ptr->IsDebug();
return false;
}
const char *SBSymbol::GetTypeAsString(lldb::SymbolType symbol_type) {
LLDB_INSTRUMENT_VA(symbol_type);
return Symbol::GetTypeAsString(symbol_type);
}
lldb::SymbolType SBSymbol::GetTypeFromString(const char *str) {
LLDB_INSTRUMENT_VA(str);
return Symbol::GetTypeFromString(str);
}

View File

@ -1570,18 +1570,6 @@ SBModule SBTarget::FindModule(const SBFileSpec &sb_file_spec) {
return sb_module;
}
SBModule SBTarget::FindModule(const SBModuleSpec &sb_module_spec) {
LLDB_INSTRUMENT_VA(this, sb_module_spec);
SBModule sb_module;
if (TargetSP target_sp = GetSP(); target_sp && sb_module_spec.IsValid()) {
// The module list is thread safe, no need to lock.
sb_module.SetSP(
target_sp->GetImages().FindFirstModule(*sb_module_spec.m_opaque_up));
}
return sb_module;
}
SBSymbolContextList SBTarget::FindCompileUnits(const SBFileSpec &sb_file_spec) {
LLDB_INSTRUMENT_VA(this, sb_file_spec);

View File

@ -347,6 +347,9 @@ Status Value::GetValueAsData(ExecutionContext *exe_ctx, DataExtractor &data,
else
data.SetAddressByteSize(sizeof(void *));
if (!type_size)
return Status::FromErrorString("type does not have a size");
uint32_t result_byte_size = *type_size;
if (m_value.GetData(data, result_byte_size))
return error; // Success;

View File

@ -392,8 +392,45 @@ bool Symbol::Compare(ConstString name, SymbolType type) const {
return false;
}
#define ENUM_TO_CSTRING(x) \
case eSymbolType##x: \
return #x;
const char *Symbol::GetTypeAsString() const {
return GetTypeAsString(static_cast<lldb::SymbolType>(m_type));
switch (m_type) {
ENUM_TO_CSTRING(Invalid);
ENUM_TO_CSTRING(Absolute);
ENUM_TO_CSTRING(Code);
ENUM_TO_CSTRING(Resolver);
ENUM_TO_CSTRING(Data);
ENUM_TO_CSTRING(Trampoline);
ENUM_TO_CSTRING(Runtime);
ENUM_TO_CSTRING(Exception);
ENUM_TO_CSTRING(SourceFile);
ENUM_TO_CSTRING(HeaderFile);
ENUM_TO_CSTRING(ObjectFile);
ENUM_TO_CSTRING(CommonBlock);
ENUM_TO_CSTRING(Block);
ENUM_TO_CSTRING(Local);
ENUM_TO_CSTRING(Param);
ENUM_TO_CSTRING(Variable);
ENUM_TO_CSTRING(VariableType);
ENUM_TO_CSTRING(LineEntry);
ENUM_TO_CSTRING(LineHeader);
ENUM_TO_CSTRING(ScopeBegin);
ENUM_TO_CSTRING(ScopeEnd);
ENUM_TO_CSTRING(Additional);
ENUM_TO_CSTRING(Compiler);
ENUM_TO_CSTRING(Instrumentation);
ENUM_TO_CSTRING(Undefined);
ENUM_TO_CSTRING(ObjCClass);
ENUM_TO_CSTRING(ObjCMetaClass);
ENUM_TO_CSTRING(ObjCIVar);
ENUM_TO_CSTRING(ReExported);
default:
break;
}
return "<unknown SymbolType>";
}
void Symbol::CalculateSymbolContext(SymbolContext *sc) {
@ -737,79 +774,6 @@ bool Symbol::operator==(const Symbol &rhs) const {
return true;
}
#define ENUM_TO_CSTRING(x) \
case eSymbolType##x: \
return #x;
const char *Symbol::GetTypeAsString(lldb::SymbolType symbol_type) {
switch (symbol_type) {
ENUM_TO_CSTRING(Invalid);
ENUM_TO_CSTRING(Absolute);
ENUM_TO_CSTRING(Code);
ENUM_TO_CSTRING(Resolver);
ENUM_TO_CSTRING(Data);
ENUM_TO_CSTRING(Trampoline);
ENUM_TO_CSTRING(Runtime);
ENUM_TO_CSTRING(Exception);
ENUM_TO_CSTRING(SourceFile);
ENUM_TO_CSTRING(HeaderFile);
ENUM_TO_CSTRING(ObjectFile);
ENUM_TO_CSTRING(CommonBlock);
ENUM_TO_CSTRING(Block);
ENUM_TO_CSTRING(Local);
ENUM_TO_CSTRING(Param);
ENUM_TO_CSTRING(Variable);
ENUM_TO_CSTRING(VariableType);
ENUM_TO_CSTRING(LineEntry);
ENUM_TO_CSTRING(LineHeader);
ENUM_TO_CSTRING(ScopeBegin);
ENUM_TO_CSTRING(ScopeEnd);
ENUM_TO_CSTRING(Additional);
ENUM_TO_CSTRING(Compiler);
ENUM_TO_CSTRING(Instrumentation);
ENUM_TO_CSTRING(Undefined);
ENUM_TO_CSTRING(ObjCClass);
ENUM_TO_CSTRING(ObjCMetaClass);
ENUM_TO_CSTRING(ObjCIVar);
ENUM_TO_CSTRING(ReExported);
}
return "<unknown SymbolType>";
}
lldb::SymbolType Symbol::GetTypeFromString(const char *str) {
std::string str_lower = llvm::StringRef(str).lower();
return llvm::StringSwitch<lldb::SymbolType>(str_lower)
.Case("absolute", eSymbolTypeAbsolute)
.Case("code", eSymbolTypeCode)
.Case("resolver", eSymbolTypeResolver)
.Case("data", eSymbolTypeData)
.Case("trampoline", eSymbolTypeTrampoline)
.Case("runtime", eSymbolTypeRuntime)
.Case("exception", eSymbolTypeException)
.Case("sourcefile", eSymbolTypeSourceFile)
.Case("headerfile", eSymbolTypeHeaderFile)
.Case("objectfile", eSymbolTypeObjectFile)
.Case("commonblock", eSymbolTypeCommonBlock)
.Case("block", eSymbolTypeBlock)
.Case("local", eSymbolTypeLocal)
.Case("param", eSymbolTypeParam)
.Case("variable", eSymbolTypeVariable)
.Case("variableType", eSymbolTypeVariableType)
.Case("lineentry", eSymbolTypeLineEntry)
.Case("lineheader", eSymbolTypeLineHeader)
.Case("scopebegin", eSymbolTypeScopeBegin)
.Case("scopeend", eSymbolTypeScopeEnd)
.Case("additional,", eSymbolTypeAdditional)
.Case("compiler", eSymbolTypeCompiler)
.Case("instrumentation", eSymbolTypeInstrumentation)
.Case("undefined", eSymbolTypeUndefined)
.Case("objcclass", eSymbolTypeObjCClass)
.Case("objcmetaclass", eSymbolTypeObjCMetaClass)
.Case("objcivar", eSymbolTypeObjCIVar)
.Case("reexported", eSymbolTypeReExported)
.Default(eSymbolTypeInvalid);
}
namespace llvm {
namespace json {
@ -840,8 +804,36 @@ bool fromJSON(const llvm::json::Value &value, lldb_private::JSONSymbol &symbol,
bool fromJSON(const llvm::json::Value &value, lldb::SymbolType &type,
llvm::json::Path path) {
if (auto str = value.getAsString()) {
llvm::StringRef str_ref = str.value_or("");
type = Symbol::GetTypeFromString(str_ref.data());
type = llvm::StringSwitch<lldb::SymbolType>(*str)
.Case("absolute", eSymbolTypeAbsolute)
.Case("code", eSymbolTypeCode)
.Case("resolver", eSymbolTypeResolver)
.Case("data", eSymbolTypeData)
.Case("trampoline", eSymbolTypeTrampoline)
.Case("runtime", eSymbolTypeRuntime)
.Case("exception", eSymbolTypeException)
.Case("sourcefile", eSymbolTypeSourceFile)
.Case("headerfile", eSymbolTypeHeaderFile)
.Case("objectfile", eSymbolTypeObjectFile)
.Case("commonblock", eSymbolTypeCommonBlock)
.Case("block", eSymbolTypeBlock)
.Case("local", eSymbolTypeLocal)
.Case("param", eSymbolTypeParam)
.Case("variable", eSymbolTypeVariable)
.Case("variableType", eSymbolTypeVariableType)
.Case("lineentry", eSymbolTypeLineEntry)
.Case("lineheader", eSymbolTypeLineHeader)
.Case("scopebegin", eSymbolTypeScopeBegin)
.Case("scopeend", eSymbolTypeScopeEnd)
.Case("additional,", eSymbolTypeAdditional)
.Case("compiler", eSymbolTypeCompiler)
.Case("instrumentation", eSymbolTypeInstrumentation)
.Case("undefined", eSymbolTypeUndefined)
.Case("objcclass", eSymbolTypeObjCClass)
.Case("objcmetaClass", eSymbolTypeObjCMetaClass)
.Case("objcivar", eSymbolTypeObjCIVar)
.Case("reexporte", eSymbolTypeReExported)
.Default(eSymbolTypeInvalid);
if (type == eSymbolTypeInvalid) {
path.report("invalid symbol type");

View File

@ -1,3 +0,0 @@
C_SOURCES := main.c
include Makefile.rules

View File

@ -1,37 +0,0 @@
"""
Test lldb-dap moduleSymbols request
"""
import lldbdap_testcase
class TestDAP_moduleSymbols(lldbdap_testcase.DAPTestCaseBase):
def test_moduleSymbols(self):
"""
Test that the moduleSymbols request returns correct symbols from the module.
"""
program = self.getBuildArtifact("a.out")
self.build_and_launch(program)
symbol_names = []
i = 0
while True:
next_symbol = self.dap_server.request_moduleSymbols(
moduleName="a.out", startIndex=i, count=1
)
self.assertIn("symbols", next_symbol["body"])
result_symbols = next_symbol["body"]["symbols"]
self.assertLessEqual(len(result_symbols), 1)
if len(result_symbols) == 0:
break
self.assertIn("name", result_symbols[0])
symbol_names.append(result_symbols[0]["name"])
i += 1
if i >= 1000:
break
self.assertGreater(len(symbol_names), 0)
self.assertIn("main", symbol_names)
self.assertIn("func1", symbol_names)
self.assertIn("func2", symbol_names)

View File

@ -1,9 +0,0 @@
int func1() { return 42; }
int func2() { return 84; }
int main() {
func1();
func2();
return 0;
}

View File

@ -792,6 +792,39 @@ void show_usage_and_exit(int exit_code) {
DEBUGSERVER_PROGRAM_NAME);
RNBLogSTDERR(" %s /path/file --attach=<process_name>\n",
DEBUGSERVER_PROGRAM_NAME);
RNBLogSTDERR("\n");
RNBLogSTDERR(" -a | --attach <pid>\n");
RNBLogSTDERR(" -w | --waitfor <name>\n");
RNBLogSTDERR(" -A | --arch <arch>\n");
RNBLogSTDERR(" -g | --debug\n");
RNBLogSTDERR(" -K | --kill-on-error\n");
RNBLogSTDERR(" -v | --verbose\n");
RNBLogSTDERR(" -V | --version\n");
RNBLogSTDERR(" -k | --lockdown\n");
RNBLogSTDERR(" -t | --applist\n");
RNBLogSTDERR(" -l | --log-file\n");
RNBLogSTDERR(" -f | --log-flags\n");
RNBLogSTDERR(" -x | --launch <auto|posix-spawn|fork-exec|springboard>\n");
RNBLogSTDERR(" -d | --waitfor-duration <seconds>\n");
RNBLogSTDERR(" -i | --waitfor-interval <usecs>\n");
RNBLogSTDERR(" -r | --native-regs\n");
RNBLogSTDERR(" -s | --studio-path <path>\n");
RNBLogSTDERR(" -I | --stdin-path <path>\n");
RNBLogSTDERR(" -O | --stdout-path <path>\n");
RNBLogSTDERR(" -E | --stderr-path <path>\n");
RNBLogSTDERR(" -n | --no-stdio\n");
RNBLogSTDERR(" -S | --setsid\n");
RNBLogSTDERR(" -D | --disable-aslr\n");
RNBLogSTDERR(" -W | --working-dir <dir>\n");
RNBLogSTDERR(" -p | --platform <arg?>\n");
RNBLogSTDERR(" -u | --unix-socket <unix socket name>\n");
RNBLogSTDERR(" -2 | --fd <file descriptor number>\n");
RNBLogSTDERR(" -P | --named-pipe <pipe>\n");
RNBLogSTDERR(" -R | --reverse-connect\n");
RNBLogSTDERR(" -e | --env <env>\n");
RNBLogSTDERR(" -F | --forward-env <env>\n");
RNBLogSTDERR(" -U | --unmask-signals\n");
exit(exit_code);
}

View File

@ -45,7 +45,6 @@ add_lldb_library(lldbDAP
Handler/LaunchRequestHandler.cpp
Handler/LocationsRequestHandler.cpp
Handler/ModulesRequestHandler.cpp
Handler/ModuleSymbolsRequestHandler.cpp
Handler/NextRequestHandler.cpp
Handler/PauseRequestHandler.cpp
Handler/ReadMemoryRequestHandler.cpp

View File

@ -1258,27 +1258,6 @@ protocol::Capabilities DAP::GetCapabilities() {
return capabilities;
}
protocol::Capabilities DAP::GetCustomCapabilities() {
protocol::Capabilities capabilities;
// Add all custom capabilities here.
const llvm::DenseSet<AdapterFeature> all_custom_features = {
protocol::eAdapterFeatureSupportsModuleSymbolsRequest,
};
for (auto &kv : request_handlers) {
llvm::SmallDenseSet<AdapterFeature, 1> features =
kv.second->GetSupportedFeatures();
for (auto &feature : features) {
if (all_custom_features.contains(feature))
capabilities.supportedFeatures.insert(feature);
}
}
return capabilities;
}
void DAP::StartEventThread() {
event_thread = std::thread(&DAP::EventThread, this);
}
@ -1635,7 +1614,6 @@ void DAP::RegisterRequests() {
// Custom requests
RegisterRequest<CompileUnitsRequestHandler>();
RegisterRequest<ModulesRequestHandler>();
RegisterRequest<ModuleSymbolsRequestHandler>();
// Testing requests
RegisterRequest<TestGetTargetBreakpointsRequestHandler>();

View File

@ -367,9 +367,6 @@ struct DAP final : private DAPTransport::MessageHandler {
/// The set of capabilities supported by this adapter.
protocol::Capabilities GetCapabilities();
/// The set of custom capabilities supported by this adapter.
protocol::Capabilities GetCustomCapabilities();
/// Debuggee will continue from stopped state.
void WillContinue() { variables.Clear(); }

View File

@ -38,37 +38,25 @@ static void SendThreadExitedEvent(DAP &dap, lldb::tid_t tid) {
dap.SendJSON(llvm::json::Value(std::move(event)));
}
/// Get capabilities based on the configured target.
static llvm::DenseSet<AdapterFeature> GetTargetBasedCapabilities(DAP &dap) {
llvm::DenseSet<AdapterFeature> capabilities;
void SendTargetBasedCapabilities(DAP &dap) {
if (!dap.target.IsValid())
return capabilities;
return;
protocol::CapabilitiesEventBody body;
const llvm::StringRef target_triple = dap.target.GetTriple();
if (target_triple.starts_with("x86"))
capabilities.insert(protocol::eAdapterFeatureStepInTargetsRequest);
body.capabilities.supportedFeatures.insert(
protocol::eAdapterFeatureStepInTargetsRequest);
// We only support restarting launch requests not attach requests.
if (dap.last_launch_request)
capabilities.insert(protocol::eAdapterFeatureRestartRequest);
return capabilities;
}
void SendExtraCapabilities(DAP &dap) {
protocol::Capabilities capabilities = dap.GetCustomCapabilities();
llvm::DenseSet<AdapterFeature> target_capabilities =
GetTargetBasedCapabilities(dap);
capabilities.supportedFeatures.insert(target_capabilities.begin(),
target_capabilities.end());
protocol::CapabilitiesEventBody body;
body.capabilities = std::move(capabilities);
body.capabilities.supportedFeatures.insert(
protocol::eAdapterFeatureRestartRequest);
// Only notify the client if supportedFeatures changed.
if (!body.capabilities.supportedFeatures.empty())
dap.Send(protocol::Event{"capabilities", std::move(body)});
dap.Send(protocol::Event{"capabilities", body});
}
// "ProcessEvent": {

View File

@ -17,8 +17,8 @@ struct DAP;
enum LaunchMethod { Launch, Attach, AttachForSuspendedLaunch };
/// Sends target based capabilities and lldb-dap custom capabilities.
void SendExtraCapabilities(DAP &dap);
/// Update capabilities based on the configured target.
void SendTargetBasedCapabilities(DAP &dap);
void SendProcessEvent(DAP &dap, LaunchMethod launch_method);

View File

@ -9,7 +9,6 @@
#include "DAP.h"
#include "EventHelper.h"
#include "LLDBUtils.h"
#include "Protocol/ProtocolEvents.h"
#include "Protocol/ProtocolRequests.h"
#include "ProtocolUtils.h"
#include "RequestHandler.h"
@ -45,10 +44,7 @@ ConfigurationDoneRequestHandler::Run(const ConfigurationDoneArguments &) const {
// Waiting until 'configurationDone' to send target based capabilities in case
// the launch or attach scripts adjust the target. The initial dummy target
// may have different capabilities than the final target.
/// Also send here custom capabilities to the client, which is consumed by the
/// lldb-dap specific editor extension.
SendExtraCapabilities(dap);
SendTargetBasedCapabilities(dap);
// Clients can request a baseline of currently existing threads after
// we acknowledge the configurationDone request.

View File

@ -1,89 +0,0 @@
//===----------------------------------------------------------------------===//
//
// 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 "DAP.h"
#include "DAPError.h"
#include "Protocol/DAPTypes.h"
#include "RequestHandler.h"
#include "lldb/API/SBAddress.h"
#include "lldb/API/SBFileSpec.h"
#include "lldb/API/SBModule.h"
#include "lldb/API/SBModuleSpec.h"
#include "lldb/Utility/UUID.h"
#include "llvm/Support/Error.h"
#include <cstddef>
using namespace lldb_dap::protocol;
namespace lldb_dap {
llvm::Expected<ModuleSymbolsResponseBody>
ModuleSymbolsRequestHandler::Run(const ModuleSymbolsArguments &args) const {
ModuleSymbolsResponseBody response;
lldb::SBModuleSpec module_spec;
if (!args.moduleId.empty()) {
llvm::SmallVector<uint8_t, 20> uuid_bytes;
if (!lldb_private::UUID::DecodeUUIDBytesFromString(args.moduleId,
uuid_bytes)
.empty())
return llvm::make_error<DAPError>("invalid module ID");
module_spec.SetUUIDBytes(uuid_bytes.data(), uuid_bytes.size());
}
if (!args.moduleName.empty()) {
lldb::SBFileSpec file_spec;
file_spec.SetFilename(args.moduleName.c_str());
module_spec.SetFileSpec(file_spec);
}
// Empty request, return empty response.
if (!module_spec.IsValid())
return response;
std::vector<Symbol> &symbols = response.symbols;
lldb::SBModule module = dap.target.FindModule(module_spec);
if (!module.IsValid())
return llvm::make_error<DAPError>("module not found");
const size_t num_symbols = module.GetNumSymbols();
const size_t start_index = args.startIndex.value_or(0);
const size_t end_index =
std::min(start_index + args.count.value_or(num_symbols), num_symbols);
for (size_t i = start_index; i < end_index; ++i) {
lldb::SBSymbol symbol = module.GetSymbolAtIndex(i);
if (!symbol.IsValid())
continue;
Symbol dap_symbol;
dap_symbol.id = symbol.GetID();
dap_symbol.type = symbol.GetType();
dap_symbol.isDebug = symbol.IsDebug();
dap_symbol.isSynthetic = symbol.IsSynthetic();
dap_symbol.isExternal = symbol.IsExternal();
lldb::SBAddress start_address = symbol.GetStartAddress();
if (start_address.IsValid()) {
lldb::addr_t file_address = start_address.GetFileAddress();
if (file_address != LLDB_INVALID_ADDRESS)
dap_symbol.fileAddress = file_address;
lldb::addr_t load_address = start_address.GetLoadAddress(dap.target);
if (load_address != LLDB_INVALID_ADDRESS)
dap_symbol.loadAddress = load_address;
}
dap_symbol.size = symbol.GetSize();
dap_symbol.name = symbol.GetName();
symbols.push_back(std::move(dap_symbol));
}
return response;
}
} // namespace lldb_dap

View File

@ -594,20 +594,6 @@ public:
llvm::Error Run(const protocol::CancelArguments &args) const override;
};
class ModuleSymbolsRequestHandler
: public RequestHandler<
protocol::ModuleSymbolsArguments,
llvm::Expected<protocol::ModuleSymbolsResponseBody>> {
public:
using RequestHandler::RequestHandler;
static llvm::StringLiteral GetCommand() { return "__lldb_moduleSymbols"; }
FeatureSet GetSupportedFeatures() const override {
return {protocol::eAdapterFeatureSupportsModuleSymbolsRequest};
}
llvm::Expected<protocol::ModuleSymbolsResponseBody>
Run(const protocol::ModuleSymbolsArguments &args) const override;
};
/// A request used in testing to get the details on all breakpoints that are
/// currently set in the target. This helps us to test "setBreakpoints" and
/// "setFunctionBreakpoints" requests to verify we have the correct set of

View File

@ -1,6 +1,4 @@
#include "Protocol/DAPTypes.h"
#include "lldb/API/SBSymbol.h"
#include "lldb/lldb-enumerations.h"
using namespace llvm;
@ -35,35 +33,4 @@ llvm::json::Value toJSON(const SourceLLDBData &SLD) {
return result;
}
bool fromJSON(const llvm::json::Value &Params, Symbol &DS, llvm::json::Path P) {
json::ObjectMapper O(Params, P);
std::string type_str;
if (!(O && O.map("id", DS.id) && O.map("isDebug", DS.isDebug) &&
O.map("isSynthetic", DS.isSynthetic) &&
O.map("isExternal", DS.isExternal) && O.map("type", type_str) &&
O.map("fileAddress", DS.fileAddress) &&
O.mapOptional("loadAddress", DS.loadAddress) &&
O.map("size", DS.size) && O.map("name", DS.name)))
return false;
DS.type = lldb::SBSymbol::GetTypeFromString(type_str.c_str());
return true;
}
llvm::json::Value toJSON(const Symbol &DS) {
json::Object result{
{"id", DS.id},
{"isDebug", DS.isDebug},
{"isSynthetic", DS.isSynthetic},
{"isExternal", DS.isExternal},
{"type", lldb::SBSymbol::GetTypeAsString(DS.type)},
{"fileAddress", DS.fileAddress},
{"loadAddress", DS.loadAddress},
{"size", DS.size},
{"name", DS.name},
};
return result;
}
} // namespace lldb_dap::protocol
} // namespace lldb_dap::protocol

View File

@ -48,38 +48,6 @@ struct SourceLLDBData {
bool fromJSON(const llvm::json::Value &, SourceLLDBData &, llvm::json::Path);
llvm::json::Value toJSON(const SourceLLDBData &);
struct Symbol {
/// The symbol id, usually the original symbol table index.
uint32_t id;
/// True if this symbol is debug information in a symbol.
bool isDebug;
/// True if this symbol is not actually in the symbol table, but synthesized
/// from other info in the object file.
bool isSynthetic;
/// True if this symbol is globally visible.
bool isExternal;
/// The symbol type.
lldb::SymbolType type;
/// The symbol file address.
lldb::addr_t fileAddress;
/// The symbol load address.
std::optional<lldb::addr_t> loadAddress;
/// The symbol size.
lldb::addr_t size;
/// The symbol name.
std::string name;
};
bool fromJSON(const llvm::json::Value &, Symbol &, llvm::json::Path);
llvm::json::Value toJSON(const Symbol &);
} // namespace lldb_dap::protocol
#endif

View File

@ -598,19 +598,4 @@ json::Value toJSON(const WriteMemoryResponseBody &WMR) {
return result;
}
bool fromJSON(const llvm::json::Value &Params, ModuleSymbolsArguments &Args,
llvm::json::Path P) {
json::ObjectMapper O(Params, P);
return O && O.map("moduleId", Args.moduleId) &&
O.map("moduleName", Args.moduleName) &&
O.mapOptional("startIndex", Args.startIndex) &&
O.mapOptional("count", Args.count);
}
llvm::json::Value toJSON(const ModuleSymbolsResponseBody &DGMSR) {
json::Object result;
result.insert({"symbols", DGMSR.symbols});
return result;
}
} // namespace lldb_dap::protocol

View File

@ -981,30 +981,6 @@ struct WriteMemoryResponseBody {
};
llvm::json::Value toJSON(const WriteMemoryResponseBody &);
struct ModuleSymbolsArguments {
/// The module UUID for which to retrieve symbols.
std::string moduleId;
/// The module path.
std::string moduleName;
/// The index of the first symbol to return; if omitted, start at the
/// beginning.
std::optional<uint32_t> startIndex;
/// The number of symbols to return; if omitted, all symbols are returned.
std::optional<uint32_t> count;
};
bool fromJSON(const llvm::json::Value &, ModuleSymbolsArguments &,
llvm::json::Path);
/// Response to `getModuleSymbols` request.
struct ModuleSymbolsResponseBody {
/// The symbols for the specified module.
std::vector<Symbol> symbols;
};
llvm::json::Value toJSON(const ModuleSymbolsResponseBody &);
} // namespace lldb_dap::protocol
#endif

View File

@ -335,8 +335,6 @@ static llvm::StringLiteral ToString(AdapterFeature feature) {
return "supportsWriteMemoryRequest";
case eAdapterFeatureTerminateDebuggee:
return "supportTerminateDebuggee";
case eAdapterFeatureSupportsModuleSymbolsRequest:
return "supportsModuleSymbolsRequest";
}
llvm_unreachable("unhandled adapter feature.");
}
@ -408,8 +406,6 @@ bool fromJSON(const llvm::json::Value &Params, AdapterFeature &feature,
eAdapterFeatureValueFormattingOptions)
.Case("supportsWriteMemoryRequest", eAdapterFeatureWriteMemoryRequest)
.Case("supportTerminateDebuggee", eAdapterFeatureTerminateDebuggee)
.Case("supportsModuleSymbolsRequest",
eAdapterFeatureSupportsModuleSymbolsRequest)
.Default(std::nullopt);
if (!parsedFeature) {

View File

@ -242,11 +242,8 @@ enum AdapterFeature : unsigned {
/// The debug adapter supports the `terminateDebuggee` attribute on the
/// `disconnect` request.
eAdapterFeatureTerminateDebuggee,
/// The debug adapter supports the `supportsModuleSymbols` request.
/// This request is a custom request of lldb-dap.
eAdapterFeatureSupportsModuleSymbolsRequest,
eAdapterFeatureFirst = eAdapterFeatureANSIStyling,
eAdapterFeatureLast = eAdapterFeatureSupportsModuleSymbolsRequest,
eAdapterFeatureLast = eAdapterFeatureTerminateDebuggee,
};
bool fromJSON(const llvm::json::Value &, AdapterFeature &, llvm::json::Path);
llvm::json::Value toJSON(const AdapterFeature &);

View File

@ -1,24 +1,20 @@
{
"name": "lldb-dap",
"version": "0.2.16",
"version": "0.2.15",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "lldb-dap",
"version": "0.2.16",
"version": "0.2.15",
"license": "Apache 2.0 License with LLVM exceptions",
"devDependencies": {
"@types/node": "^18.19.41",
"@types/tabulator-tables": "^6.2.10",
"@types/vscode": "1.75.0",
"@types/vscode-webview": "^1.57.5",
"@vscode/debugprotocol": "^1.68.0",
"@vscode/vsce": "^3.2.2",
"esbuild": "^0.25.9",
"prettier": "^3.4.2",
"prettier-plugin-curly": "^0.3.1",
"tabulator-tables": "^6.3.1",
"typescript": "^5.7.3"
},
"engines": {
@ -322,448 +318,6 @@
"node": ">=6.9.0"
}
},
"node_modules/@esbuild/aix-ppc64": {
"version": "0.25.9",
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.9.tgz",
"integrity": "sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA==",
"cpu": [
"ppc64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"aix"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/android-arm": {
"version": "0.25.9",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.9.tgz",
"integrity": "sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ==",
"cpu": [
"arm"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/android-arm64": {
"version": "0.25.9",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.9.tgz",
"integrity": "sha512-IDrddSmpSv51ftWslJMvl3Q2ZT98fUSL2/rlUXuVqRXHCs5EUF1/f+jbjF5+NG9UffUDMCiTyh8iec7u8RlTLg==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/android-x64": {
"version": "0.25.9",
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.9.tgz",
"integrity": "sha512-I853iMZ1hWZdNllhVZKm34f4wErd4lMyeV7BLzEExGEIZYsOzqDWDf+y082izYUE8gtJnYHdeDpN/6tUdwvfiw==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/darwin-arm64": {
"version": "0.25.9",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.9.tgz",
"integrity": "sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/darwin-x64": {
"version": "0.25.9",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.9.tgz",
"integrity": "sha512-jhHfBzjYTA1IQu8VyrjCX4ApJDnH+ez+IYVEoJHeqJm9VhG9Dh2BYaJritkYK3vMaXrf7Ogr/0MQ8/MeIefsPQ==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/freebsd-arm64": {
"version": "0.25.9",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.9.tgz",
"integrity": "sha512-z93DmbnY6fX9+KdD4Ue/H6sYs+bhFQJNCPZsi4XWJoYblUqT06MQUdBCpcSfuiN72AbqeBFu5LVQTjfXDE2A6Q==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/freebsd-x64": {
"version": "0.25.9",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.9.tgz",
"integrity": "sha512-mrKX6H/vOyo5v71YfXWJxLVxgy1kyt1MQaD8wZJgJfG4gq4DpQGpgTB74e5yBeQdyMTbgxp0YtNj7NuHN0PoZg==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-arm": {
"version": "0.25.9",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.9.tgz",
"integrity": "sha512-HBU2Xv78SMgaydBmdor38lg8YDnFKSARg1Q6AT0/y2ezUAKiZvc211RDFHlEZRFNRVhcMamiToo7bDx3VEOYQw==",
"cpu": [
"arm"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-arm64": {
"version": "0.25.9",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.9.tgz",
"integrity": "sha512-BlB7bIcLT3G26urh5Dmse7fiLmLXnRlopw4s8DalgZ8ef79Jj4aUcYbk90g8iCa2467HX8SAIidbL7gsqXHdRw==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-ia32": {
"version": "0.25.9",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.9.tgz",
"integrity": "sha512-e7S3MOJPZGp2QW6AK6+Ly81rC7oOSerQ+P8L0ta4FhVi+/j/v2yZzx5CqqDaWjtPFfYz21Vi1S0auHrap3Ma3A==",
"cpu": [
"ia32"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-loong64": {
"version": "0.25.9",
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.9.tgz",
"integrity": "sha512-Sbe10Bnn0oUAB2AalYztvGcK+o6YFFA/9829PhOCUS9vkJElXGdphz0A3DbMdP8gmKkqPmPcMJmJOrI3VYB1JQ==",
"cpu": [
"loong64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-mips64el": {
"version": "0.25.9",
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.9.tgz",
"integrity": "sha512-YcM5br0mVyZw2jcQeLIkhWtKPeVfAerES5PvOzaDxVtIyZ2NUBZKNLjC5z3/fUlDgT6w89VsxP2qzNipOaaDyA==",
"cpu": [
"mips64el"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-ppc64": {
"version": "0.25.9",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.9.tgz",
"integrity": "sha512-++0HQvasdo20JytyDpFvQtNrEsAgNG2CY1CLMwGXfFTKGBGQT3bOeLSYE2l1fYdvML5KUuwn9Z8L1EWe2tzs1w==",
"cpu": [
"ppc64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-riscv64": {
"version": "0.25.9",
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.9.tgz",
"integrity": "sha512-uNIBa279Y3fkjV+2cUjx36xkx7eSjb8IvnL01eXUKXez/CBHNRw5ekCGMPM0BcmqBxBcdgUWuUXmVWwm4CH9kg==",
"cpu": [
"riscv64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-s390x": {
"version": "0.25.9",
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.9.tgz",
"integrity": "sha512-Mfiphvp3MjC/lctb+7D287Xw1DGzqJPb/J2aHHcHxflUo+8tmN/6d4k6I2yFR7BVo5/g7x2Monq4+Yew0EHRIA==",
"cpu": [
"s390x"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-x64": {
"version": "0.25.9",
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.9.tgz",
"integrity": "sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/netbsd-arm64": {
"version": "0.25.9",
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.9.tgz",
"integrity": "sha512-9jNJl6FqaUG+COdQMjSCGW4QiMHH88xWbvZ+kRVblZsWrkXlABuGdFJ1E9L7HK+T0Yqd4akKNa/lO0+jDxQD4Q==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"netbsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/netbsd-x64": {
"version": "0.25.9",
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.9.tgz",
"integrity": "sha512-RLLdkflmqRG8KanPGOU7Rpg829ZHu8nFy5Pqdi9U01VYtG9Y0zOG6Vr2z4/S+/3zIyOxiK6cCeYNWOFR9QP87g==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"netbsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/openbsd-arm64": {
"version": "0.25.9",
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.9.tgz",
"integrity": "sha512-YaFBlPGeDasft5IIM+CQAhJAqS3St3nJzDEgsgFixcfZeyGPCd6eJBWzke5piZuZ7CtL656eOSYKk4Ls2C0FRQ==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"openbsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/openbsd-x64": {
"version": "0.25.9",
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.9.tgz",
"integrity": "sha512-1MkgTCuvMGWuqVtAvkpkXFmtL8XhWy+j4jaSO2wxfJtilVCi0ZE37b8uOdMItIHz4I6z1bWWtEX4CJwcKYLcuA==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"openbsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/openharmony-arm64": {
"version": "0.25.9",
"resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.9.tgz",
"integrity": "sha512-4Xd0xNiMVXKh6Fa7HEJQbrpP3m3DDn43jKxMjxLLRjWnRsfxjORYJlXPO4JNcXtOyfajXorRKY9NkOpTHptErg==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"openharmony"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/sunos-x64": {
"version": "0.25.9",
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.9.tgz",
"integrity": "sha512-WjH4s6hzo00nNezhp3wFIAfmGZ8U7KtrJNlFMRKxiI9mxEK1scOMAaa9i4crUtu+tBr+0IN6JCuAcSBJZfnphw==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"sunos"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/win32-arm64": {
"version": "0.25.9",
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.9.tgz",
"integrity": "sha512-mGFrVJHmZiRqmP8xFOc6b84/7xa5y5YvR1x8djzXpJBSv/UsNK6aqec+6JDjConTgvvQefdGhFDAs2DLAds6gQ==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/win32-ia32": {
"version": "0.25.9",
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.9.tgz",
"integrity": "sha512-b33gLVU2k11nVx1OhX3C8QQP6UHQK4ZtN56oFWvVXvz2VkDoe6fbG8TOgHFxEvqeqohmRnIHe5A1+HADk4OQww==",
"cpu": [
"ia32"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/win32-x64": {
"version": "0.25.9",
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.9.tgz",
"integrity": "sha512-PPOl1mi6lpLNQxnGoyAfschAodRFYXJ+9fs6WHXz7CSWKbOqiMZsubC+BQsVKuul+3vKLuwTHsS2c2y9EoKwxQ==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@isaacs/cliui": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
@ -845,13 +399,6 @@
"undici-types": "~5.26.4"
}
},
"node_modules/@types/tabulator-tables": {
"version": "6.2.10",
"resolved": "https://registry.npmjs.org/@types/tabulator-tables/-/tabulator-tables-6.2.10.tgz",
"integrity": "sha512-g6o0gG3lu/ozmxPw9rLY1p57T6rvV8OhbJKyzWwPwjdnN3JuSQ3gWxb06v2+dl2tdoqNXTvlylipSSKpS8UzzQ==",
"dev": true,
"license": "MIT"
},
"node_modules/@types/vscode": {
"version": "1.75.0",
"resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.75.0.tgz",
@ -859,13 +406,6 @@
"dev": true,
"license": "MIT"
},
"node_modules/@types/vscode-webview": {
"version": "1.57.5",
"resolved": "https://registry.npmjs.org/@types/vscode-webview/-/vscode-webview-1.57.5.tgz",
"integrity": "sha512-iBAUYNYkz+uk1kdsq05fEcoh8gJmwT3lqqFPN7MGyjQ3HVloViMdo7ZJ8DFIP8WOK74PjOEilosqAyxV2iUFUw==",
"dev": true,
"license": "MIT"
},
"node_modules/@vscode/debugprotocol": {
"version": "1.68.0",
"resolved": "https://registry.npmjs.org/@vscode/debugprotocol/-/debugprotocol-1.68.0.tgz",
@ -1629,48 +1169,6 @@
"node": ">= 0.4"
}
},
"node_modules/esbuild": {
"version": "0.25.9",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.9.tgz",
"integrity": "sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
"bin": {
"esbuild": "bin/esbuild"
},
"engines": {
"node": ">=18"
},
"optionalDependencies": {
"@esbuild/aix-ppc64": "0.25.9",
"@esbuild/android-arm": "0.25.9",
"@esbuild/android-arm64": "0.25.9",
"@esbuild/android-x64": "0.25.9",
"@esbuild/darwin-arm64": "0.25.9",
"@esbuild/darwin-x64": "0.25.9",
"@esbuild/freebsd-arm64": "0.25.9",
"@esbuild/freebsd-x64": "0.25.9",
"@esbuild/linux-arm": "0.25.9",
"@esbuild/linux-arm64": "0.25.9",
"@esbuild/linux-ia32": "0.25.9",
"@esbuild/linux-loong64": "0.25.9",
"@esbuild/linux-mips64el": "0.25.9",
"@esbuild/linux-ppc64": "0.25.9",
"@esbuild/linux-riscv64": "0.25.9",
"@esbuild/linux-s390x": "0.25.9",
"@esbuild/linux-x64": "0.25.9",
"@esbuild/netbsd-arm64": "0.25.9",
"@esbuild/netbsd-x64": "0.25.9",
"@esbuild/openbsd-arm64": "0.25.9",
"@esbuild/openbsd-x64": "0.25.9",
"@esbuild/openharmony-arm64": "0.25.9",
"@esbuild/sunos-x64": "0.25.9",
"@esbuild/win32-arm64": "0.25.9",
"@esbuild/win32-ia32": "0.25.9",
"@esbuild/win32-x64": "0.25.9"
}
},
"node_modules/escape-string-regexp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
@ -3059,13 +2557,6 @@
"node": ">=4"
}
},
"node_modules/tabulator-tables": {
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/tabulator-tables/-/tabulator-tables-6.3.1.tgz",
"integrity": "sha512-qFW7kfadtcaISQIibKAIy0f3eeIXUVi8242Vly1iJfMD79kfEGzfczNuPBN/80hDxHzQJXYbmJ8VipI40hQtfA==",
"dev": true,
"license": "MIT"
},
"node_modules/tar-fs": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz",

View File

@ -29,15 +29,11 @@
],
"devDependencies": {
"@types/node": "^18.19.41",
"@types/tabulator-tables": "^6.2.10",
"@types/vscode": "1.75.0",
"@types/vscode-webview": "^1.57.5",
"@vscode/debugprotocol": "^1.68.0",
"@vscode/vsce": "^3.2.2",
"esbuild": "^0.25.9",
"prettier": "^3.4.2",
"prettier-plugin-curly": "^0.3.1",
"tabulator-tables": "^6.3.1",
"typescript": "^5.7.3"
},
"activationEvents": [
@ -46,11 +42,8 @@
],
"main": "./out/extension",
"scripts": {
"bundle-symbols-table-view": "npx tsc -p src-ts/webview --noEmit && npx esbuild src-ts/webview/symbols-table-view.ts --bundle --format=iife --outdir=./out/webview",
"bundle-tabulator": "cp node_modules/tabulator-tables/dist/js/tabulator.min.js ./out/webview/ && cp node_modules/tabulator-tables/dist/css/tabulator_midnight.min.css ./out/webview/ && cp node_modules/tabulator-tables/dist/css/tabulator_simple.min.css ./out/webview/",
"bundle-webview": "npm run bundle-symbols-table-view && npm run bundle-tabulator",
"vscode:prepublish": "npm run bundle-webview && tsc -p ./",
"watch": "npm run bundle-webview && tsc -watch -p ./",
"vscode:prepublish": "tsc -p ./",
"watch": "tsc -watch -p ./",
"format": "npx prettier './src-ts/' --write",
"package": "rm -rf ./out/lldb-dap.vsix && vsce package --out ./out/lldb-dap.vsix",
"publish": "vsce publish",
@ -266,15 +259,6 @@
{
"command": "lldb-dap.modules.copyProperty",
"title": "Copy Value"
},
{
"command": "lldb-dap.modules.showSymbols",
"title": "Show Module Symbols"
},
{
"category": "lldb-dap",
"command": "lldb-dap.debug.showSymbols",
"title": "Show Symbols of a Module"
}
],
"menus": {
@ -282,24 +266,12 @@
{
"command": "lldb-dap.modules.copyProperty",
"when": "false"
},
{
"command": "lldb-dap.modules.showSymbols",
"when": "false"
},
{
"command": "lldb-dap.debug.showSymbols",
"when": "debuggersAvailable && debugType == 'lldb-dap' && lldb-dap.supportsModuleSymbolsRequest"
}
],
"view/item/context": [
{
"command": "lldb-dap.modules.copyProperty",
"when": "view == lldb-dap.modules && viewItem == property"
},
{
"command": "lldb-dap.modules.showSymbols",
"when": "view == lldb-dap.modules && viewItem == module && lldb-dap.supportsModuleSymbolsRequest"
}
]
},

View File

@ -69,10 +69,6 @@ const configurations: Record<string, DefaultConfig> = {
terminateCommands: { type: "stringArray", default: [] },
};
export function getDefaultConfigKey(key: string): string | number | boolean | string[] | undefined {
return configurations[key]?.default;
}
export class LLDBDapConfigurationProvider
implements vscode.DebugConfigurationProvider
{

View File

@ -1,17 +1,11 @@
import { DebugProtocol } from "@vscode/debugprotocol";
import * as vscode from "vscode";
export interface LLDBDapCapabilities extends DebugProtocol.Capabilities {
/** The debug adapter supports the `moduleSymbols` request. */
supportsModuleSymbolsRequest?: boolean;
}
/** A helper type for mapping event types to their corresponding data type. */
// prettier-ignore
interface EventMap {
"module": DebugProtocol.ModuleEvent;
"exited": DebugProtocol.ExitedEvent;
"capabilities": DebugProtocol.CapabilitiesEvent;
}
/** A type assertion to check if a ProtocolMessage is an event or if it is a specific event. */
@ -45,9 +39,6 @@ export class DebugSessionTracker
private modulesChanged = new vscode.EventEmitter<
vscode.DebugSession | undefined
>();
private sessionReceivedCapabilities =
new vscode.EventEmitter<[ vscode.DebugSession, LLDBDapCapabilities ]>();
private sessionExited = new vscode.EventEmitter<vscode.DebugSession>();
/**
* Fired when modules are changed for any active debug session.
@ -57,15 +48,6 @@ export class DebugSessionTracker
onDidChangeModules: vscode.Event<vscode.DebugSession | undefined> =
this.modulesChanged.event;
/** Fired when a debug session is initialized. */
onDidReceiveSessionCapabilities:
vscode.Event<[ vscode.DebugSession, LLDBDapCapabilities ]> =
this.sessionReceivedCapabilities.event;
/** Fired when a debug session is exiting. */
onDidExitSession: vscode.Event<vscode.DebugSession> =
this.sessionExited.event;
constructor(private logger: vscode.LogOutputChannel) {
this.onDidChangeModules(this.moduleChangedListener, this);
vscode.debug.onDidChangeActiveDebugSession((session) =>
@ -164,10 +146,6 @@ export class DebugSessionTracker
this.logger.info(
`Session "${session.name}" exited with code ${exitCode}`,
);
this.sessionExited.fire(session);
} else if (isEvent(message, "capabilities")) {
this.sessionReceivedCapabilities.fire([ session, message.body.capabilities ]);
}
}
}

View File

@ -12,7 +12,6 @@ import {
ModuleProperty,
} from "./ui/modules-data-provider";
import { LogFilePathProvider } from "./logging";
import { SymbolsProvider } from "./ui/symbols-provider";
/**
* This class represents the extension and manages its life cycle. Other extensions
@ -20,7 +19,6 @@ import { SymbolsProvider } from "./ui/symbols-provider";
*/
export class LLDBDapExtension extends DisposableContext {
constructor(
context: vscode.ExtensionContext,
logger: vscode.LogOutputChannel,
logFilePath: LogFilePathProvider,
outputChannel: vscode.OutputChannel,
@ -54,12 +52,10 @@ export class LLDBDapExtension extends DisposableContext {
vscode.window.registerUriHandler(new LaunchUriHandler()),
);
this.pushSubscription(vscode.commands.registerCommand(
vscode.commands.registerCommand(
"lldb-dap.modules.copyProperty",
(node: ModuleProperty) => vscode.env.clipboard.writeText(node.value),
));
this.pushSubscription(new SymbolsProvider(sessionTracker, context));
);
}
}
@ -71,7 +67,7 @@ export async function activate(context: vscode.ExtensionContext) {
outputChannel.info("LLDB-DAP extension activating...");
const logFilePath = new LogFilePathProvider(context, outputChannel);
context.subscriptions.push(
new LLDBDapExtension(context, outputChannel, logFilePath, outputChannel),
new LLDBDapExtension(outputChannel, logFilePath, outputChannel),
);
outputChannel.info("LLDB-DAP extension activated");
}

View File

@ -1,14 +0,0 @@
export {};
/// The symbol type we get from the lldb-dap server
export declare interface SymbolType {
id: number;
isDebug: boolean;
isSynthetic: boolean;
isExternal: boolean;
type: string;
fileAddress: number;
loadAddress?: number;
size: number;
name: string;
}

View File

@ -19,7 +19,6 @@ class ModuleItem extends vscode.TreeItem {
constructor(module: DebugProtocol.Module) {
super(module.name, vscode.TreeItemCollapsibleState.Collapsed);
this.description = module.symbolStatus;
this.contextValue = "module";
}
static getProperties(module: DebugProtocol.Module): ModuleProperty[] {

View File

@ -1,127 +0,0 @@
import * as vscode from "vscode";
import { DebugProtocol } from "@vscode/debugprotocol";
import { DebugSessionTracker } from "../debug-session-tracker";
import { DisposableContext } from "../disposable-context";
import { SymbolType } from "..";
import { getSymbolsTableHTMLContent } from "./symbols-webview-html";
import { getDefaultConfigKey } from "../debug-configuration-provider";
export class SymbolsProvider extends DisposableContext {
constructor(
private readonly tracker: DebugSessionTracker,
private readonly extensionContext: vscode.ExtensionContext,
) {
super();
this.pushSubscription(vscode.commands.registerCommand(
"lldb-dap.debug.showSymbols",
() => {
const session = vscode.debug.activeDebugSession;
if (!session) return;
this.SelectModuleAndShowSymbols(session);
},
));
this.pushSubscription(vscode.commands.registerCommand(
"lldb-dap.modules.showSymbols",
(moduleItem: DebugProtocol.Module) => {
const session = vscode.debug.activeDebugSession;
if (!session) return;
this.showSymbolsForModule(session, moduleItem);
},
));
this.tracker.onDidReceiveSessionCapabilities(([ _session, capabilities ]) => {
if (capabilities.supportsModuleSymbolsRequest) {
vscode.commands.executeCommand(
"setContext", "lldb-dap.supportsModuleSymbolsRequest", true);
}
});
this.tracker.onDidExitSession((_session) => {
vscode.commands.executeCommand("setContext", "lldb-dap.supportsModuleSymbolsRequest", false);
});
}
private async SelectModuleAndShowSymbols(session: vscode.DebugSession) {
const modules = this.tracker.debugSessionModules(session);
if (!modules || modules.length === 0) {
return;
}
// Let the user select a module to show symbols for
const selectedModule = await vscode.window.showQuickPick(modules.map(m => new ModuleQuickPickItem(m)), {
placeHolder: "Select a module to show symbols for"
});
if (!selectedModule) {
return;
}
this.showSymbolsForModule(session, selectedModule.module);
}
private async showSymbolsForModule(session: vscode.DebugSession, module: DebugProtocol.Module) {
try {
const symbols = await this.getSymbolsForModule(session, module.id.toString());
this.showSymbolsInNewTab(module.name.toString(), symbols);
} catch (error) {
if (error instanceof Error) {
vscode.window.showErrorMessage("Failed to retrieve symbols: " + error.message);
} else {
vscode.window.showErrorMessage("Failed to retrieve symbols due to an unknown error.");
}
return;
}
}
private async getSymbolsForModule(session: vscode.DebugSession, moduleId: string): Promise<SymbolType[]> {
const symbols_response: { symbols: Array<SymbolType> } = await session.customRequest("__lldb_moduleSymbols", { moduleId, moduleName: '' });
return symbols_response?.symbols || [];
}
private async showSymbolsInNewTab(moduleName: string, symbols: SymbolType[]) {
const panel = vscode.window.createWebviewPanel(
"lldb-dap.symbols",
`Symbols for ${moduleName}`,
vscode.ViewColumn.Active,
{
enableScripts: true,
localResourceRoots: [
this.getExtensionResourcePath()
]
}
);
let tabulatorJsFilename = "tabulator_simple.min.css";
if (vscode.window.activeColorTheme.kind === vscode.ColorThemeKind.Dark || vscode.window.activeColorTheme.kind === vscode.ColorThemeKind.HighContrast) {
tabulatorJsFilename = "tabulator_midnight.min.css";
}
const tabulatorCssPath = panel.webview.asWebviewUri(vscode.Uri.joinPath(this.getExtensionResourcePath(), tabulatorJsFilename));
const tabulatorJsPath = panel.webview.asWebviewUri(vscode.Uri.joinPath(this.getExtensionResourcePath(), "tabulator.min.js"));
const symbolsTableScriptPath = panel.webview.asWebviewUri(vscode.Uri.joinPath(this.getExtensionResourcePath(), "symbols-table-view.js"));
panel.webview.html = getSymbolsTableHTMLContent(tabulatorJsPath, tabulatorCssPath, symbolsTableScriptPath);
panel.webview.postMessage({ command: "updateSymbols", symbols: symbols });
}
private getExtensionResourcePath(): vscode.Uri {
return vscode.Uri.joinPath(this.extensionContext.extensionUri, "out", "webview");
}
}
class ModuleQuickPickItem implements vscode.QuickPickItem {
constructor(public readonly module: DebugProtocol.Module) {}
get label(): string {
return this.module.name;
}
get description(): string {
return this.module.id.toString();
}
}

View File

@ -1,51 +0,0 @@
import * as vscode from "vscode";
export function getSymbolsTableHTMLContent(tabulatorJsPath: vscode.Uri, tabulatorCssPath: vscode.Uri, symbolsTableScriptPath: vscode.Uri): string {
return `<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link href="${tabulatorCssPath}" rel="stylesheet">
<style>
.tabulator {
background-color: var(--vscode-editor-background);
color: var(--vscode-editor-foreground);
}
.tabulator .tabulator-header .tabulator-col {
background-color: var(--vscode-editor-background);
color: var(--vscode-editor-foreground);
}
.tabulator-row {
background-color: var(--vscode-editor-background);
color: var(--vscode-editor-foreground);
}
.tabulator-row.tabulator-row-even {
background-color: var(--vscode-editor-background);
color: var(--vscode-editor-foreground);
}
.tabulator-row.tabulator-selected {
background-color: var(--vscode-editor-background);
color: var(--vscode-editor-foreground);
}
.tabulator-cell {
text-overflow: clip !important;
}
#symbols-table {
width: 100%;
height: 100vh;
}
</style>
</head>
<body>
<div id="symbols-table"></div>
<script src="${tabulatorJsPath}"></script>
<script src="${symbolsTableScriptPath}"></script>
</body>
</html>`;
}

View File

@ -1,114 +0,0 @@
import type { CellComponent, ColumnDefinition } from "tabulator-tables";
import type { SymbolType } from ".."
/// SVG from https://github.com/olifolkerd/tabulator/blob/master/src/js/modules/Format/defaults/formatters/tickCross.js
/// but with the default font color.
/// hopefully in the future we can set the color as parameter: https://github.com/olifolkerd/tabulator/pull/4791
const TICK_ELEMENT = `<svg enable-background="new 0 0 24 24" height="14" width="14" viewBox="0 0 24 24" xml:space="preserve" ><path fill="var(--vscode-editor-foreground)" clip-rule="evenodd" d="M21.652,3.211c-0.293-0.295-0.77-0.295-1.061,0L9.41,14.34 c-0.293,0.297-0.771,0.297-1.062,0L3.449,9.351C3.304,9.203,3.114,9.13,2.923,9.129C2.73,9.128,2.534,9.201,2.387,9.351 l-2.165,1.946C0.078,11.445,0,11.63,0,11.823c0,0.194,0.078,0.397,0.223,0.544l4.94,5.184c0.292,0.296,0.771,0.776,1.062,1.07 l2.124,2.141c0.292,0.293,0.769,0.293,1.062,0l14.366-14.34c0.293-0.294,0.293-0.777,0-1.071L21.652,3.211z" fill-rule="evenodd"/></svg>`;
function getTabulatorHexaFormatter(padding: number): (cell: CellComponent) => string {
return (cell: CellComponent) => {
const val = cell.getValue();
if (val === undefined || val === null) {
return "";
}
return val !== undefined ? "0x" + val.toString(16).toLowerCase().padStart(padding, "0") : "";
};
}
const SYMBOL_TABLE_COLUMNS: ColumnDefinition[] = [
{ title: "ID", field: "id", headerTooltip: true, sorter: "number", widthGrow: 0.6 },
{
title: "Name",
field: "name",
headerTooltip: true,
sorter: "string",
widthGrow: 2.5,
minWidth: 200,
tooltip : (_event: MouseEvent, cell: CellComponent) => {
const rowData = cell.getRow().getData();
return rowData.name;
}
},
{
title: "Debug",
field: "isDebug",
headerTooltip: true,
hozAlign: "center",
widthGrow: 0.8,
formatter: "tickCross",
formatterParams: {
tickElement: TICK_ELEMENT,
crossElement: false,
}
},
{
title: "Synthetic",
field: "isSynthetic",
headerTooltip: true,
hozAlign: "center",
widthGrow: 0.8,
formatter: "tickCross",
formatterParams: {
tickElement: TICK_ELEMENT,
crossElement: false,
}
},
{
title: "External",
field: "isExternal",
headerTooltip: true,
hozAlign: "center",
widthGrow: 0.8,
formatter: "tickCross",
formatterParams: {
tickElement: TICK_ELEMENT,
crossElement: false,
}
},
{ title: "Type", field: "type", sorter: "string" },
{
title: "File Address",
field: "fileAddress",
headerTooltip: true,
sorter: "number",
widthGrow : 1.25,
formatter: getTabulatorHexaFormatter(16),
},
{
title: "Load Address",
field: "loadAddress",
headerTooltip: true,
sorter: "number",
widthGrow : 1.25,
formatter: getTabulatorHexaFormatter(16),
},
{ title: "Size", field: "size", headerTooltip: true, sorter: "number", formatter: getTabulatorHexaFormatter(8) },
];
const vscode = acquireVsCodeApi();
const previousState: any = vscode.getState();
declare const Tabulator: any; // HACK: real definition comes from tabulator.min.js
const SYMBOLS_TABLE = new Tabulator("#symbols-table", {
height: "100vh",
columns: SYMBOL_TABLE_COLUMNS,
layout: "fitColumns",
data: previousState?.symbols || [],
});
function updateSymbolsTable(symbols: SymbolType[]) {
SYMBOLS_TABLE.setData(symbols);
}
window.addEventListener("message", (event: MessageEvent<any>) => {
const message = event.data;
switch (message.command) {
case "updateSymbols":
vscode.setState({ symbols: message.symbols });
updateSymbolsTable(message.symbols);
break;
}
});

View File

@ -1,15 +0,0 @@
{
"compilerOptions": {
"moduleResolution": "node",
"module": "esnext",
"outDir": "out",
"rootDir": ".",
"sourceMap": true,
"strict": true,
"noEmit": true,
"target": "es2017"
},
"include": [
"./"
],
}

View File

@ -1,6 +1,5 @@
{
"compilerOptions": {
"moduleResolution": "node",
"module": "commonjs",
"outDir": "out",
"rootDir": "src-ts",
@ -13,6 +12,5 @@
],
"exclude": [
"node_modules",
"src-ts/webview",
]
}

View File

@ -15,6 +15,7 @@ add_lldb_unittest(LLDBCoreTests
SourceManagerTest.cpp
TelemetryTest.cpp
UniqueCStringMapTest.cpp
Value.cpp
LINK_COMPONENTS
Support

View File

@ -0,0 +1,39 @@
//===----------------------------------------------------------------------===//
//
// 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 "lldb/Core/Value.h"
#include "Plugins/Platform/MacOSX/PlatformMacOSX.h"
#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
#include "TestingSupport/SubsystemRAII.h"
#include "TestingSupport/Symbol/ClangTestUtils.h"
#include "lldb/Utility/DataExtractor.h"
#include "gtest/gtest.h"
using namespace lldb_private;
using namespace lldb_private::clang_utils;
TEST(ValueTest, GetValueAsData) {
SubsystemRAII<FileSystem, HostInfo, PlatformMacOSX> subsystems;
auto holder = std::make_unique<clang_utils::TypeSystemClangHolder>("test");
auto *clang = holder->GetAST();
Value v(Scalar(42));
DataExtractor extractor;
// no compiler type
Status status = v.GetValueAsData(nullptr, extractor, nullptr);
ASSERT_TRUE(status.Fail());
// with compiler type
v.SetCompilerType(clang->GetBasicType(lldb::BasicType::eBasicTypeChar));
status = v.GetValueAsData(nullptr, extractor, nullptr);
ASSERT_TRUE(status.Success());
}

View File

@ -1,7 +1,6 @@
add_lldb_unittest(DAPTests
DAPErrorTest.cpp
DAPTest.cpp
DAPTypesTest.cpp
FifoFilesTest.cpp
Handler/DisconnectTest.cpp
Handler/ContinueTest.cpp

View File

@ -1,60 +0,0 @@
//===-- DAPTypesTest.cpp ----------------------------------------*- C++ -*-===//
//
// 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 "Protocol/DAPTypes.h"
#include "TestingSupport/TestUtilities.h"
#include "lldb/lldb-enumerations.h"
#include "llvm/Testing/Support/Error.h"
#include "gtest/gtest.h"
#include <optional>
using namespace llvm;
using namespace lldb;
using namespace lldb_dap;
using namespace lldb_dap::protocol;
using lldb_private::roundtripJSON;
TEST(DAPTypesTest, SourceLLDBData) {
SourceLLDBData source_data;
source_data.persistenceData =
PersistenceData{"module_path123", "symbol_name456"};
llvm::Expected<SourceLLDBData> deserialized_data = roundtripJSON(source_data);
ASSERT_THAT_EXPECTED(deserialized_data, llvm::Succeeded());
EXPECT_EQ(source_data.persistenceData->module_path,
deserialized_data->persistenceData->module_path);
EXPECT_EQ(source_data.persistenceData->symbol_name,
deserialized_data->persistenceData->symbol_name);
}
TEST(DAPTypesTest, DAPSymbol) {
Symbol symbol;
symbol.id = 42;
symbol.isDebug = true;
symbol.isExternal = false;
symbol.isSynthetic = true;
symbol.type = lldb::eSymbolTypeTrampoline;
symbol.fileAddress = 0x12345678;
symbol.loadAddress = 0x87654321;
symbol.size = 64;
symbol.name = "testSymbol";
llvm::Expected<Symbol> deserialized_symbol = roundtripJSON(symbol);
ASSERT_THAT_EXPECTED(deserialized_symbol, llvm::Succeeded());
EXPECT_EQ(symbol.id, deserialized_symbol->id);
EXPECT_EQ(symbol.isDebug, deserialized_symbol->isDebug);
EXPECT_EQ(symbol.isExternal, deserialized_symbol->isExternal);
EXPECT_EQ(symbol.isSynthetic, deserialized_symbol->isSynthetic);
EXPECT_EQ(symbol.type, deserialized_symbol->type);
EXPECT_EQ(symbol.fileAddress, deserialized_symbol->fileAddress);
EXPECT_EQ(symbol.loadAddress, deserialized_symbol->loadAddress);
EXPECT_EQ(symbol.size, deserialized_symbol->size);
EXPECT_EQ(symbol.name, deserialized_symbol->name);
}

View File

@ -175,6 +175,24 @@ if(LLVM_ENABLE_EXPENSIVE_CHECKS)
endif()
endif()
CHECK_CXX_SOURCE_COMPILES("
#include <iosfwd>
#if !defined(__GLIBCXX__)
#error Not libstdc++
#endif
int main() { return 0; }
" LLVM_USES_LIBSTDCXX)
option(GLIBCXX_USE_CXX11_ABI "Use new libstdc++ CXX11 ABI" ON)
if (LLVM_USES_LIBSTDCXX)
if (GLIBCXX_USE_CXX11_ABI)
add_compile_definitions(_GLIBCXX_USE_CXX11_ABI=1)
else()
add_compile_definitions(_GLIBCXX_USE_CXX11_ABI=0)
endif()
endif()
if (LLVM_ENABLE_STRICT_FIXED_SIZE_VECTORS)
add_compile_definitions(STRICT_FIXED_SIZE_VECTORS)
endif()

View File

@ -17,6 +17,7 @@
#include "llvm/MC/MCLinkerOptimizationHint.h"
#include "llvm/MC/MCObjectWriter.h"
#include "llvm/MC/MCSectionMachO.h"
#include "llvm/MC/MCSymbolMachO.h"
#include "llvm/MC/StringTableBuilder.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/EndianStream.h"
@ -110,7 +111,7 @@ public:
private:
/// Helper struct for containing some precomputed information on symbols.
struct MachSymbolData {
const MCSymbol *Symbol;
const MCSymbolMachO *Symbol;
uint64_t StringIndex;
uint8_t SectionIndex;
@ -119,7 +120,7 @@ private:
};
struct IndirectSymbolData {
MCSymbol *Symbol;
MCSymbolMachO *Symbol;
MCSection *Section;
};

View File

@ -17029,8 +17029,7 @@ SDValue DAGCombiner::visitFADDForFMACombine(SDNode *N) {
// fadd (G, (fma A, B, (fma (C, D, (fmul (E, F)))))) -->
// fma A, B, (fma C, D, fma (E, F, G)).
// This requires reassociation because it changes the order of operations.
bool CanReassociate =
Options.UnsafeFPMath || N->getFlags().hasAllowReassociation();
bool CanReassociate = N->getFlags().hasAllowReassociation();
if (CanReassociate) {
SDValue FMA, E;
if (isFusedOp(N0) && N0.hasOneUse()) {
@ -17696,7 +17695,7 @@ SDValue DAGCombiner::visitFADD(SDNode *N) {
// If 'unsafe math' or reassoc and nsz, fold lots of things.
// TODO: break out portions of the transformations below for which Unsafe is
// considered and which do not require both nsz and reassoc
if (((Options.UnsafeFPMath && Options.NoSignedZerosFPMath) ||
if ((Options.NoSignedZerosFPMath ||
(Flags.hasAllowReassociation() && Flags.hasNoSignedZeros())) &&
AllowNewConst) {
// fadd (fadd x, c1), c2 -> fadd x, c1 + c2
@ -17783,7 +17782,7 @@ SDValue DAGCombiner::visitFADD(SDNode *N) {
}
} // enable-unsafe-fp-math && AllowNewConst
if (((Options.UnsafeFPMath && Options.NoSignedZerosFPMath) ||
if ((Options.NoSignedZerosFPMath ||
(Flags.hasAllowReassociation() && Flags.hasNoSignedZeros()))) {
// Fold fadd(vecreduce(x), vecreduce(y)) -> vecreduce(fadd(x, y))
if (SDValue SD = reassociateReduction(ISD::VECREDUCE_FADD, ISD::FADD, DL,
@ -17886,7 +17885,7 @@ SDValue DAGCombiner::visitFSUB(SDNode *N) {
}
}
if (((Options.UnsafeFPMath && Options.NoSignedZerosFPMath) ||
if ((Options.NoSignedZerosFPMath ||
(Flags.hasAllowReassociation() && Flags.hasNoSignedZeros())) &&
N1.getOpcode() == ISD::FADD) {
// X - (X + Y) -> -Y
@ -18026,7 +18025,6 @@ SDValue DAGCombiner::visitFMUL(SDNode *N) {
ConstantFPSDNode *N1CFP = isConstOrConstSplatFP(N1, true);
EVT VT = N->getValueType(0);
SDLoc DL(N);
const TargetOptions &Options = DAG.getTarget().Options;
const SDNodeFlags Flags = N->getFlags();
SelectionDAG::FlagInserter FlagsInserter(DAG, N);
@ -18050,7 +18048,7 @@ SDValue DAGCombiner::visitFMUL(SDNode *N) {
if (SDValue NewSel = foldBinOpIntoSelect(N))
return NewSel;
if (Options.UnsafeFPMath || Flags.hasAllowReassociation()) {
if (Flags.hasAllowReassociation()) {
// fmul (fmul X, C1), C2 -> fmul X, C1 * C2
if (DAG.isConstantFPBuildVectorOrConstantFP(N1) &&
N0.getOpcode() == ISD::FMUL) {
@ -18227,8 +18225,7 @@ template <class MatchContextClass> SDValue DAGCombiner::visitFMA(SDNode *N) {
!DAG.isConstantFPBuildVectorOrConstantFP(N1))
return matcher.getNode(ISD::FMA, DL, VT, N1, N0, N2);
bool CanReassociate =
Options.UnsafeFPMath || N->getFlags().hasAllowReassociation();
bool CanReassociate = N->getFlags().hasAllowReassociation();
if (CanReassociate) {
// (fma x, c1, (fmul x, c2)) -> (fmul x, c1+c2)
if (matcher.match(N2, ISD::FMUL) && N0 == N2.getOperand(0) &&
@ -18323,9 +18320,8 @@ SDValue DAGCombiner::combineRepeatedFPDivisors(SDNode *N) {
// TODO: Limit this transform based on optsize/minsize - it always creates at
// least 1 extra instruction. But the perf win may be substantial enough
// that only minsize should restrict this.
bool UnsafeMath = DAG.getTarget().Options.UnsafeFPMath;
const SDNodeFlags Flags = N->getFlags();
if (LegalDAG || (!UnsafeMath && !Flags.hasAllowReciprocal()))
if (LegalDAG || !Flags.hasAllowReciprocal())
return SDValue();
// Skip if current node is a reciprocal/fneg-reciprocal.
@ -18362,7 +18358,7 @@ SDValue DAGCombiner::combineRepeatedFPDivisors(SDNode *N) {
// This division is eligible for optimization only if global unsafe math
// is enabled or if this division allows reciprocal formation.
if (UnsafeMath || U->getFlags().hasAllowReciprocal())
if (U->getFlags().hasAllowReciprocal())
Users.insert(U);
}
}
@ -18987,7 +18983,9 @@ SDValue DAGCombiner::visitFP_ROUND(SDNode *N) {
// single-step fp_round we want to fold to.
// In other words, double rounding isn't the same as rounding.
// Also, this is a value preserving truncation iff both fp_round's are.
if (DAG.getTarget().Options.UnsafeFPMath || N0IsTrunc)
if ((N->getFlags().hasAllowContract() &&
N0->getFlags().hasAllowContract()) ||
N0IsTrunc)
return DAG.getNode(
ISD::FP_ROUND, DL, VT, N0.getOperand(0),
DAG.getIntPtrConstant(NIsTrunc && N0IsTrunc, DL, /*isTarget=*/true));

View File

@ -2340,6 +2340,9 @@ void MCAsmStreamer::AddEncodingComment(const MCInst &Inst,
getAssembler().getEmitter().encodeInstruction(Inst, Code, Fixups, STI);
// RISC-V instructions are always little-endian, even on BE systems.
bool ForceLE = getContext().getTargetTriple().isRISCV();
// If we are showing fixups, create symbolic markers in the encoded
// representation. We do this by making a per-bit map to the fixup item index,
// then trying to display it as nicely as possible.
@ -2394,7 +2397,10 @@ void MCAsmStreamer::AddEncodingComment(const MCInst &Inst,
unsigned Bit = (Code[i] >> j) & 1;
unsigned FixupBit;
if (MAI->isLittleEndian())
// RISC-V instructions are always little-endian.
// The FixupMap is indexed by actual bit positions in the LE
// instruction.
if (MAI->isLittleEndian() || ForceLE)
FixupBit = i * 8 + j;
else
FixupBit = i * 8 + (7-j);

View File

@ -149,7 +149,7 @@ void MCMachOStreamer::emitEHSymAttributes(const MCSymbol *Symbol,
MCSymbol *EHSymbol) {
auto *Sym = static_cast<const MCSymbolMachO *>(Symbol);
getAssembler().registerSymbol(*Symbol);
if (Symbol->isExternal())
if (Sym->isExternal())
emitSymbolAttribute(EHSymbol, MCSA_Global);
if (Sym->isWeakDefinition())
emitSymbolAttribute(EHSymbol, MCSA_WeakDefinition);
@ -372,12 +372,13 @@ void MCMachOStreamer::emitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {
void MCMachOStreamer::emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
Align ByteAlignment) {
auto &Sym = static_cast<MCSymbolMachO &>(*Symbol);
// FIXME: Darwin 'as' does appear to allow redef of a .comm by itself.
assert(Symbol->isUndefined() && "Cannot define a symbol twice!");
getAssembler().registerSymbol(*Symbol);
Symbol->setExternal(true);
Symbol->setCommon(Size, ByteAlignment);
getAssembler().registerSymbol(Sym);
Sym.setExternal(true);
Sym.setCommon(Size, ByteAlignment);
}
void MCMachOStreamer::emitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
@ -460,7 +461,8 @@ void MCMachOStreamer::finishImpl() {
}
void MCMachOStreamer::finalizeCGProfileEntry(const MCSymbolRefExpr *&SRE) {
const MCSymbol *S = &SRE->getSymbol();
auto *S =
static_cast<MCSymbolMachO *>(const_cast<MCSymbol *>(&SRE->getSymbol()));
if (getAssembler().registerSymbol(*S))
S->setExternal(true);
}

View File

@ -1864,11 +1864,13 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info,
Lex();
}
if (MAI.hasSubsectionsViaSymbols() && CFIStartProcLoc &&
Sym->isExternal() && !static_cast<MCSymbolMachO *>(Sym)->isAltEntry())
return Error(StartTokLoc, "non-private labels cannot appear between "
".cfi_startproc / .cfi_endproc pairs") &&
Error(*CFIStartProcLoc, "previous .cfi_startproc was here");
if (MAI.isMachO() && CFIStartProcLoc) {
auto *SymM = static_cast<MCSymbolMachO *>(Sym);
if (SymM->isExternal() && !SymM->isAltEntry())
return Error(StartTokLoc, "non-private labels cannot appear between "
".cfi_startproc / .cfi_endproc pairs") &&
Error(*CFIStartProcLoc, "previous .cfi_startproc was here");
}
if (discardLTOSymbol(IDVal))
return false;

View File

@ -39,7 +39,7 @@
#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/MCSymbolCOFF.h"
#include "llvm/MC/MCTargetOptions.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
@ -3009,8 +3009,8 @@ bool MasmParser::parseDirectiveEquate(StringRef IDVal, StringRef Name,
return false;
}
MCSymbol *Sym = getContext().getOrCreateSymbol(Var.Name);
auto *Sym =
static_cast<MCSymbolCOFF *>(getContext().getOrCreateSymbol(Var.Name));
const MCConstantExpr *PrevValue =
Sym->isVariable()
? dyn_cast_or_null<MCConstantExpr>(Sym->getVariableValue())
@ -4521,7 +4521,8 @@ bool MasmParser::parseDirectiveExtern() {
KnownType[Name.lower()] = Type;
}
MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
auto *Sym =
static_cast<MCSymbolCOFF *>(getContext().getOrCreateSymbol(Name));
Sym->setExternal(true);
getStreamer().emitSymbolAttribute(Sym, MCSA_Extern);

View File

@ -128,14 +128,14 @@ void MCXCOFFStreamer::emitXCOFFCInfoSym(StringRef Name, StringRef Metadata) {
void MCXCOFFStreamer::emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
Align ByteAlignment) {
auto *Sym = static_cast<MCSymbolXCOFF *>(Symbol);
auto &Sym = static_cast<MCSymbolXCOFF &>(*Symbol);
getAssembler().registerSymbol(*Symbol);
Symbol->setExternal(Sym->getStorageClass() != XCOFF::C_HIDEXT);
Sym.setExternal(Sym.getStorageClass() != XCOFF::C_HIDEXT);
Symbol->setCommon(Size, ByteAlignment);
// Default csect align is 4, but common symbols have explicit alignment values
// and we should honor it.
Sym->getRepresentedCsect()->setAlignment(ByteAlignment);
Sym.getRepresentedCsect()->setAlignment(ByteAlignment);
// Emit the alignment and storage for the variable to the section.
emitValueToAlignment(ByteAlignment);

View File

@ -383,7 +383,7 @@ const MCSymbol &MachObjectWriter::findAliasedSymbol(const MCSymbol &Sym) const {
}
void MachObjectWriter::writeNlist(MachSymbolData &MSD, const MCAssembler &Asm) {
auto *Symbol = static_cast<const MCSymbolMachO *>(MSD.Symbol);
auto *Symbol = MSD.Symbol;
const auto &Data = static_cast<const MCSymbolMachO &>(*Symbol);
auto *AliasedSymbol =
static_cast<const MCSymbolMachO *>(&findAliasedSymbol(*Symbol));
@ -602,15 +602,16 @@ void MachObjectWriter::computeSymbolTable(
// match 'as'. Even though it doesn't matter for correctness, this is
// important for letting us diff .o files.
for (const MCSymbol &Symbol : Asm.symbols()) {
auto &Sym = static_cast<const MCSymbolMachO &>(Symbol);
// Ignore non-linker visible symbols.
if (!static_cast<const MCSymbolMachO &>(Symbol).isSymbolLinkerVisible())
if (!Sym.isSymbolLinkerVisible())
continue;
if (!Symbol.isExternal() && !Symbol.isUndefined())
if (!Sym.isExternal() && !Sym.isUndefined())
continue;
MachSymbolData MSD;
MSD.Symbol = &Symbol;
MSD.Symbol = &Sym;
MSD.StringIndex = StringTable.getOffset(Symbol.getName());
if (Symbol.isUndefined()) {
@ -628,15 +629,16 @@ void MachObjectWriter::computeSymbolTable(
// Now add the data for local symbols.
for (const MCSymbol &Symbol : Asm.symbols()) {
auto &Sym = static_cast<const MCSymbolMachO &>(Symbol);
// Ignore non-linker visible symbols.
if (!static_cast<const MCSymbolMachO &>(Symbol).isSymbolLinkerVisible())
if (!Sym.isSymbolLinkerVisible())
continue;
if (Symbol.isExternal() || Symbol.isUndefined())
if (Sym.isExternal() || Sym.isUndefined())
continue;
MachSymbolData MSD;
MSD.Symbol = &Symbol;
MSD.Symbol = &Sym;
MSD.StringIndex = StringTable.getOffset(Symbol.getName());
if (Symbol.isAbsolute()) {

View File

@ -1561,7 +1561,7 @@ uint64_t WasmObjectWriter::writeOneObject(MCAssembler &Asm,
<< toString(WS.getType().value_or(wasm::WASM_SYMBOL_TYPE_DATA))
<< " '" << S << "'"
<< " isDefined=" << S.isDefined() << " isExternal="
<< S.isExternal() << " isTemporary=" << S.isTemporary()
<< WS.isExternal() << " isTemporary=" << S.isTemporary()
<< " isWeak=" << WS.isWeak() << " isHidden=" << WS.isHidden()
<< " isVariable=" << WS.isVariable() << "\n");

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