201 Commits

Author SHA1 Message Date
Timm Baeder
df3f629735
[clang][bytecode][NFC] Only collect non-null args if we have to (#152074)
Only do this if the function really has a NonNullArg.
2025-08-05 07:54:25 +02:00
Kazu Hirata
39ca925ffe
[AST] Use llvm::iterator_range::empty (NFC) (#151904) 2025-08-04 07:40:38 -07:00
Timm Baeder
76e38ca981
[clang][bytecode] Try to load primitive values directly (#151833)
Instead of doing a GetPtrLocal + Load or GetPtrGlobal + Load pair, try
to load the value directly.
2025-08-04 12:28:33 +02:00
Timm Baeder
a1dfcc6e81
[clang][bytecode] Fix D3DCOLORtoUBYTE4 hlsl test (#151819)
HLSL is using CK_FloatingToIntegral casts to cast to vectors, which we
don't support (neither does the current interpreter). Also fix a crash
when trying to promote the HLSL bool, which can't be promoted it seems.
2025-08-02 16:18:38 +02:00
Timm Baeder
f4aaf6fe5c
[clang][bytecode] Fix a crash in codegen (#151515)
getRecord() can return nullptr if any one of the fields does, in this
case because the array is too large for us to allocate.
2025-07-31 15:50:02 +02:00
Timm Baeder
2c00df3c93
[clang][bytecode][NFC] Remove LabelScope (#151498)
It did almost nothing
2025-07-31 13:34:21 +02:00
Eli Friedman
0bbe1b30fa
[clang] Forbid reinterpret_cast of function pointers in constexpr. (#150557)
This has been explicitly forbidden since C++11, but somehow the edge
case of converting a function pointer to void* using a cast like
`(void*)f` wasn't handled.

Fixes #150340 .
2025-07-30 18:15:17 -07:00
Timm Baeder
904de95e71
[clang][bytecode][NFC] Fix a few clang-tidy complaints (#150940) 2025-07-28 15:57:49 +02:00
Timm Baeder
23eef9a7c4
[clang][bytecode] Activate primitive fields before initializing them (#149963)
The initializer itself might need the field to be active.
2025-07-23 06:09:27 +02:00
Timm Baeder
01b47eb86c
[clang][bytecode] Only implicitly start lifetime of trivially-default-constructible union members (#149835)
See
faee39baa8
2025-07-23 05:28:37 +02:00
Timm Baeder
e39ee62c5b
[clang][bytecode] Use OptPrimType instead of std::optional<PrimType> (#149812)
We use this construct a lot. Use something similar to clang's
UnsignedOrNone.

This results in some slighy compile time improvements:
https://llvm-compile-time-tracker.com/compare.php?from=17a4b0399d161a3b89d8f0ce82add1638f23f5d4&to=a251d81ecd0ed45dd190462663155fdb303ef04d&stat=instructions:u
2025-07-21 17:16:13 +02:00
Timm Baeder
fed6db45df
[clang][bytecode] Diagnose dereferencing a null pointer (#149330) 2025-07-19 21:39:06 +02:00
Timm Baeder
ef49ed4829
[clang][bytecode] Use bytecode interpreter in isPotentialConstantExprU… (#149462)
…nevaluated

Fake a function call to the given function and evaluate the given
expression as if it was part of that function call.

Fixes #149383
2025-07-19 07:18:51 +02:00
Timm Baeder
17d3029331
[clang][bytecode] Make union activation more granular (#148835)
Only activate things if the syntactical structure suggests so. This adds
a bunch of new opcodes to control whether to activate in stores, etc.

Fixes #134789
2025-07-16 09:03:33 +02:00
Timm Baeder
c0422733e3
[clang][bytecode] Check lambda captures before binding decls (#148130)
If the given decls is a lambda capture (but also a BindingDecl), handle
it as a lambda capture instead of a BindingDecl.
2025-07-11 10:51:59 +02:00
Timm Baeder
376b3f7049
[clang][bytecode] Devirtualize calls during con- and destruction (#147685)
When compiliung compiling a ctor or dtor, we need to devirtualize the
virtual function calls so we always call the implementation of the
current class.
2025-07-09 14:37:10 +02:00
Timm Baeder
65f94d7518
[clang][bytecode] Don't crash on erroneous switch conditions (#147533)
Not attaching a test since I've only seen this when compiling a large
c++26 test case as c++17.
2025-07-08 17:14:02 +02:00
Timm Baeder
4c98da2cad
[clang][bytecode] Create a temporary for discarded CXXBindTemporaryExprs (#147303)
So we run the destructor.
2025-07-08 06:00:52 +02:00
Timm Baeder
9c7320e5d3
[clang][bytecode] Fix visiting for-range loop variable (#147188)
Make sure we're properly registering DecompositionDecls.
2025-07-06 18:59:24 +02:00
Timm Baeder
258c048f64
[clang][bytecode] Fix copy constructors for empty unions (#147050)
Nothing to do in that case.
2025-07-04 16:10:12 +02:00
Yanzuo Liu
90e20d4f42
[Clang][Bytecode] Implement P1061 structured binding pack (#146474)
Other part of this feature was implemented by #121417.
2025-07-01 19:15:12 +08:00
Timm Baeder
36cf51d16e
[clang][bytecode] Classify variable initializer, not the decl (#146338)
I'm not attaching a test case because I wasn't able to reproduce. The
backtrace looks as follows:

```
    frame #10: 0x00007fffdedf0b0d libclang-cpp.so.21.0git`clang::interp::Context::evaluateAsInitializer(this=0x00007c6f839f62f0, Parent=0x00007bff7f3820e0, VD=0x00007bff77ce24b0, Result=0x00007bff7165cd78) at Context.cpp:123:16
    frame #11: 0x00007fffde7bcc2f libclang-cpp.so.21.0git`clang::Expr::EvaluateAsInitializer(this=0x00007bff77ce3078, Value=0x00007bff7165cd78, Ctx=0x00007e9f839f8200, VD=0x00007bff77ce24b0, Notes=0x00007bff7f0d1620, IsConstantInitialization=false) const at ExprConstant.cpp:17096:20
    frame #12: 0x00007fffdde7ca84 libclang-cpp.so.21.0git`clang::VarDecl::evaluateValueImpl(this=0x00007bff77ce24b0, Notes=0x00007bff7f0d1620, IsConstantInitialization=false) const at Decl.cpp:2607:23
    frame #13: 0x00007fffdde7a4a2 libclang-cpp.so.21.0git`clang::VarDecl::evaluateValue(this=0x00007bff77ce24b0) const at Decl.cpp:2583:10
    frame #14: 0x00007fffdde7a0d7 libclang-cpp.so.21.0git`clang::VarDecl::hasInitWithSideEffects(this=0x00007bff77ce24b0) const at Decl.cpp:2458:39
    frame #15: 0x00007fffe8c2e77b libclang-cpp.so.21.0git`clang::ASTDeclWriter::VisitVarDecl(this=0x00007bff7f381b50, D=0x00007bff77ce24b0) at ASTWriterDecl.cpp:1308:27
    frame #16: 0x00007fffe8c58bf8 libclang-cpp.so.21.0git`clang::declvisitor::Base<std::add_pointer, clang::ASTDeclWriter, void>::Visit(this=0x00007bff7f381b50, D=0x00007bff77ce24b0) at DeclNodes.inc:296:1
    frame #17: 0x00007fffe8c1ad7e libclang-cpp.so.21.0git`clang::ASTDeclWriter::Visit(this=0x00007bff7f381b50, D=0x00007bff77ce24b0) at ASTWriterDecl.cpp:460:31
    frame #18: 0x00007fffe8c4f5ae libclang-cpp.so.21.0git`clang::ASTWriter::WriteDecl(this=0x00007e0f83dd8608, Context=0x00007e9f839f8200, D=0x00007bff77ce24b0) at ASTWriterDecl.cpp:3060:5
    frame #19: 0x00007fffe8a908a7 libclang-cpp.so.21.0git`clang::ASTWriter::WriteDeclAndTypes(this=0x00007e0f83dd8608, Context=0x00007e9f839f8200) at ASTWriter.cpp:6243:9
    frame #20: 0x00007fffe8a805f5 libclang-cpp.so.21.0git`clang::ASTWriter::WriteASTCore(this=0x00007e0f83dd8608, SemaPtr=0x00007e8f83cd3200, isysroot=(Data = "", Length = 0), WritingModule=0x00007e0f83d5bc18) at ASTWriter.cpp:6083:5
    frame #21: 0x00007fffe8a7cfa2 libclang-cpp.so.21.0git`clang::ASTWriter::WriteAST(this=0x00007e0f83dd8608, Subject=PointerUnion<clang::Sema *, clang::Preprocessor *> @ 0x00007bff7f18e640, OutputFile=(Data = "/home/tbaeder/code/llvm-project/build/runtimes/runtimes-bins/libcxx/test/libcxx/clang_modules_include.gen.py/Output/complex.h.compile.pass.cpp.dir/t.tmp/1WNKSCAH8NSAM/std-PE20VSNDCJ1A.pcm", Length = 187), WritingModule=0x00007e0f83d5bc18, isysroot=(Data = "", Length = 0), ShouldCacheASTInMemory=true) at ASTWriter.cpp:5434:32
    frame #22: 0x00007fffe8cd2168 libclang-cpp.so.21.0git`clang::PCHGenerator::HandleTranslationUnit(this=0x00007e0f83dd8500, Ctx=0x00007e9f839f8200) at GeneratePCH.cpp:86:30
    frame #23: 0x00007fffe9595e11 libclang-cpp.so.21.0git`clang::MultiplexConsumer::HandleTranslationUnit(this=0x00007c5f83a00300, Ctx=0x00007e9f839f8200) at MultiplexConsumer.cpp:339:15
    frame #24: 0x00007fffdc94121d libclang-cpp.so.21.0git`clang::ParseAST(S=0x00007e8f83cd3200, PrintStats=false, SkipFunctionBodies=false) at ParseAST.cpp:183:13
    frame #25: 0x00007fffe9480085 libclang-cpp.so.21.0git`clang::ASTFrontendAction::ExecuteAction(this=0x00007bff7efb9020) at FrontendAction.cpp:1339:3
    frame #26: 0x00007fffe947e650 libclang-cpp.so.21.0git`clang::FrontendAction::Execute(this=0x00007bff7efb9020) at FrontendAction.cpp:1221:3
    frame #27: 0x00007fffe915a163 libclang-cpp.so.21.0git`clang::CompilerInstance::ExecuteAction(this=0x00007d2f839ef000, Act=0x00007bff7efb9020) at CompilerInstance.cpp:1055:33
    frame #28: 0x00007fffe9175bbf libclang-cpp.so.21.0git`clang::CompilerInstance::compileModule(clang::SourceLocation, llvm::StringRef, llvm::StringRef, clang::CompilerInstance&)::$_0::operator()(this=0x00007bff805225e0) const at CompilerInstance.cpp:1291:18
[...]
    frame #39: 0x00007fffa3ab2a35 libLLVM.so.21.0git`void* llvm:🧵:ThreadProxy<std::tuple<void (*)(void*), (anonymous namespace)::RunSafelyOnThreadInfo*>>(Ptr=0x00007c1f839e4330) at thread.h:58:5
    frame #40: 0x000000000039933b clang++`asan_thread_start(void*) + 155
    frame #41: 0x00007fff84a7dfa8 libc.so.6`start_thread + 952
    frame #42: 0x00007fff84b01fcc libc.so.6`__clone3 + 44
```

where we encounter this declaration:
```
VarDecl 0x7bff790764b0 </[...]test-suite-install/include/c++/v1/__condition_variable/condition_variable.h:49:3, col:53> col:8 in std.condition_variable.condition_variable hidden referenced __result_max '_Rep' cinit `-CallExpr 0x7bff79077078 <col:23, col:53> 'type':'long long'
  `-ImplicitCastExpr 0x7bff79077058 <col:23, col:49> 'type (*)() noexcept' <FunctionToPointerDecay>
    `-DeclRefExpr 0x7bff79076670 <col:23, col:49> 'type () noexcept' lvalue CXXMethod 0x7bff791df1f8 'max' 'type () noexcept'
      `-NestedNameSpecifier TypeSpec 'numeric_limits<__ns_rep>':'std::numeric_limits<long long>'
```

which looks fine at first, but the declaration type does not:
```
TemplateTypeParmType 0x7bff79074dd0 '_Rep' dependent depth 0 index 0 `-TemplateTypeParm 0x7bff79074d70 '_Rep'
```
we cannot classify this, so we later run into an assertion because we
assume `PT_Ptr` while the value on the stack is of type `classify(long
long)`.

Work around this by only looking at the initializer type in that case.

For the record, the command line that crashed could be extracted from
`ninja check-cxx` and was:

```
/home/tbaeder/code/llvm-project/build/bin/clang++ /home/tbaeder/code/llvm-project/build/runtimes/runtimes-bins/libcxx/test/libcxx/clang_modules_include.gen.py/complex.h.compile.pass.cpp -pthread --target=x86_64-redhat-linux -nostdinc++ -I /home/tbaeder/code/llvm-project/build/runtimes/runtimes-bins/libcxx/test-suite-install/include/x86_64-redhat-linux/c++/v1 -I /home/tbaeder/code/llvm-project/build/runtimes/runtimes-bins/libcxx/test-suite-install/include/c++/v1 -I /home/tbaeder/code/llvm-project/libcxx/test/support -std=c++26 -Werror -Wall -Wctad-maybe-unsupported -Wextra -Wshadow -Wundef -Wunused-template -Wno-unused-command-line-argument -Wno-attributes -Wno-pessimizing-move -Wno-noexcept-type -Wno-atomic-alignment -Wno-reserved-module-identifier -Wdeprecated-copy -Wdeprecated-copy-dtor -Wshift-negative-value -Wno-user-defined-literals -Wno-tautological-compare -Wsign-compare -Wunused-variable -Wunused-parameter
 -Wunreachable-code -Wno-unused-local-typedef -Wno-local-type-template-args -Wno-c++11-extensions -Wno-unknown-pragmas -Wno-pass-failed -Wno-mismatched-new-delete -Wno-redundant-move -Wno-self-move -Wno-nullability-completeness -D_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER -D_LIBCPP_ENABLE_EXPERIMENTAL -D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_EXTENSIVE -Werror=thread-safety -Wuser-defined-warnings -fmodules -fcxx-modules -fmodules-cache-path=/home/tbaeder/code/llvm-project/build/runtimes/runtimes-bins/libcxx/test/libcxx/clang_modules_include.gen.py/Output/complex.h.compile.pass.cpp.dir/t.tmp -fsyntax-only
```
2025-06-30 19:50:48 +02:00
Rahul Joshi
6cf656eca7
[NFC][Clang][AST] Drop llvm:: in front of ArrayRef/MutableArrayRef (#145207) 2025-06-23 13:10:42 -07:00
Timm Baeder
32fc625a3f
Reapply "Reapply "[clang][bytecode] Allocate IntegralAP and Floating … (#145014)
…types usi… (#144676)"

This reverts commit 68471d29eed2c49f9b439e505b3f24d387d54f97.

IntegralAP contains a union:
  union {
    uint64_t *Memory = nullptr;
    uint64_t Val;
  };

On 64bit systems, both Memory and Val have the same size. However, on 32
bit system, Val is 64bit and Memory only 32bit. Which means the default
initializer for Memory will only zero half of Val. We fixed this by
zero-initializing Val explicitly in the IntegralAP(unsigned BitWidth)
constructor.


See also the discussion in
https://github.com/llvm/llvm-project/pull/144246
2025-06-20 18:06:01 +02:00
Timm Bäder
68471d29ee Revert "Reapply "[clang][bytecode] Allocate IntegralAP and Floating types usi… (#144676)"
This reverts commit 7c15edb306932e41c159f3d69c161ed0d89d47b7.

This still breaks clang-armv8-quick:
https://lab.llvm.org/buildbot/#/builders/154/builds/17587
2025-06-18 15:17:53 +02:00
Timm Baeder
7c15edb306
Reapply "[clang][bytecode] Allocate IntegralAP and Floating types usi… (#144676)
…ng an allocator (#144246)"

This reverts commit 57828fec760f086b334ce0cb1c465fc559dcaea4.
2025-06-18 14:37:29 +02:00
Timm Bäder
57828fec76 Revert "[clang][bytecode] Allocate IntegralAP and Floating types using an allocator (#144246)"
This reverts commit c66be289901b3f035187d391e80e3610d7d6232e.

This breaks the armv8-quick builder:
https://lab.llvm.org/buildbot/#/builders/154/builds/17549
2025-06-17 21:08:23 +02:00
Timm Baeder
c66be28990
[clang][bytecode] Allocate IntegralAP and Floating types using an allocator (#144246)
Both `APInt` and `APFloat` will heap-allocate memory themselves using
the system allocator when the size of their data exceeds 64 bits.

This is why clang has `APNumericStorage`, which allocates its memory
using an allocator (via `ASTContext`) instead. Calling `getValue()` on
an ast node like that will then create a new `APInt`/`APFloat` , which
will copy the data (in the `APFloat` case, we even copy it twice).
That's sad but whatever.

In the bytecode interpreter, we have a similar problem. Large integers
and floating-point values are placement-new allocated into the
`InterpStack` (or into the bytecode, which is a `vector<std::byte>`).
When we then later interrupt interpretation, we don't run the destructor
for all items on the stack, which means we leak the memory the
`APInt`/`APFloat` (which backs the `IntegralAP`/`Floating` the
interpreter uses).

Fix this by using an approach similar to the one used in the AST. Add an
allocator to `InterpState`, which is used for temporaries and local
values. Those values will be freed at the end of interpretation. For
global variables, we need to promote the values to global lifetime,
which we do via `InitGlobal` and `FinishInitGlobal` ops.

Interestingly, this results in a slight _improvement_ in compile times:
https://llvm-compile-time-tracker.com/compare.php?from=6bfcdda9b1ddf0900f82f7e30cb5e3253a791d50&to=88d1d899127b408f0fb0f385c2c58e6283195049&stat=instructions:u
(but don't ask me why).

Fixes https://github.com/llvm/llvm-project/issues/139012
2025-06-17 18:31:06 +02:00
Sirui Mu
567647888e
[clang][bytecode] Avoid revisiting decomposition decl in visitDeclRef (#144226)
This simple patch removes the code to revisit `DecompositionDecl` in
`visitDeclRef`. The revisit will try to emit the initializer of the
`DecompositionDecl`, which could result in evaluation errors if the
`DecompositionDecl` is not within a constexpr context.
2025-06-15 23:00:16 +08:00
Timm Baeder
294643e4bd
[clang][bytecode] Check lifetime of all ptr bases in placement-new (#141272)
placement-new'ing an object with a dead base object is not allowed, so
we need to check all the pointer bases.
2025-05-24 14:17:26 +02:00
Timm Baeder
d01355645b
[clang][bytecode] Check downcasts for the correct type (#140689)
In multiple inheritance/diamond scenarios, we might arrive at the wrong
type.
2025-05-20 11:19:24 +02:00
Timm Baeder
bb92c80dbb
[clang][bytecode][NFC] Simplify VisitCompoundLiteralExpr (#140547) 2025-05-19 17:11:34 +02:00
Timm Baeder
bca39f4e8f
[clang][bytecode] Add a scope to function calls (#140441)
We need a place to destroy the temporaries created for call arguments.
2025-05-19 11:49:27 +02:00
Timm Baeder
e5f8998ac8
[clang][bytecode] Explicitly start variable lifetimes via placement new (#140221)
placement new /std::construct{,_at} can resurrect a variable after it's
destructor has been called.
2025-05-16 12:48:22 +02:00
Timm Baeder
767a203a9e
[clang][bytecode] Fix discarded LValueToRValueBitCasts (#140034)
We handle discarding fine, but we used to ignore all discarded cast
expressions. Handle bitcasts differently.
2025-05-15 13:17:29 +02:00
Timm Baeder
9ca8248a91
[clang] Save ShuffleVectorExpr args as ConstantExpr (#139709)
The passed indices have to be constant integers anyway, which we verify
before creating the ShuffleVectorExpr. Use the value we create there and
save the indices using a ConstantExpr instead. This way, we don't have
to evaluate the args every time we call getShuffleMaskIdx().
2025-05-14 16:13:01 +02:00
Timm Baeder
a6ae2237aa
[clang][bytecode][NFC] Avoid an implicit integer conversion (#139845)
getCharByteWidth() returns an unsigned.
2025-05-14 09:16:20 +02:00
Timm Baeder
4554c85239
[clang][bytecode] Use IsNonNull op in visitBool() (#139846)
We don't need to emit the nullptr and compare to it anymore.
2025-05-14 09:14:03 +02:00
Timm Baeder
83ce8a44bb
[clang][bytecode] Get BuiltinID from the direct callee (#139675)
getBuiltinCallee() just checks the direct callee for its builtin id
anyway, so let's do this ourselves.
2025-05-13 11:11:47 +02:00
Timm Baeder
3de2fa91e1
[clang][bytecode] Avoid classifying in visitArrayElemInit() (#139674)
We usually call this more than once, but the type of the initializer
never changes. Let's classify only once and pass that to
visitArrayElemInit().
2025-05-13 11:01:59 +02:00
Timm Baeder
7439d7bdf5
[clang][bytecode] Slightly optimize integral casts of literals (#138879)
We often see initializers like

unsigned a = 10;

which take an integer literal and immediately cast it to another type.
Recognize this pattern and omit the cast, simply emitting the value as a
different type directly.

This reduces the instruction count by up to 0.13%:
http://llvm-compile-time-tracker.com/compare.php?from=303436c6d16518b35288d63a859506ffcc1681e4&to=648f5202f906d1606390b2d1081e4502dc74acc2&stat=instructions:u
2025-05-09 09:02:25 +02:00
Timm Baeder
dc28f9d087
[clang][ExprConstant] Bail out on invalid lambda capture inits (#138832)
Fixes https://github.com/llvm/llvm-project/issues/138824
2025-05-08 05:22:11 +02:00
Timm Baeder
c51be1be3a
[clang][bytecode] Fix checking for integer overflow (#137962)
We need to evaluate both the True/False expressions of a conditional
operator as well as the LHS/RHS of a binary operator in more cases.
2025-05-01 07:35:33 +02:00
Timm Baeder
15579a8e72
[clang][bytecode] Check array sizes against step limit (#137679) 2025-04-29 05:47:22 +02:00
Timm Baeder
959905a5ad
[clang][bytecode] Don't create Function instances for builtins (#137618)
Now that we don't use them anymore in InterpBuiltin.cpp and we don't
create frames for them anymore anyway, just don't create Function
instances.
2025-04-28 14:08:42 +02:00
Timm Baeder
e086d7b146
[clang][bytecode] Don't create function frames for builtin calls (#137607)
They don't have local variables etc. so don't create frames for them.
2025-04-28 13:11:15 +02:00
Timm Baeder
7904298c79
[clang][bytecode] Don't ignore discarded ArraySubScriptExprs (#137526)
We need to evaluate them since the index might be out of bounds.
2025-04-27 20:10:41 +02:00
Timm Baeder
a50269e999
[clang][bytecode] Diagnose dynamic_cast before C++20 (#137442)
Emit a CCE diagnostic.
2025-04-26 06:23:34 +02:00
Timm Baeder
d775b911c9
[clang][bytecode] Diagnose pseudo dtor calls before C++20 (#137303) 2025-04-25 13:03:58 +02:00
Timm Baeder
211b51e471
[clang][bytecode] Propagate IsVolatile bit to subobjects (#137293)
For
```c++
  struct S {
    constexpr S(int=0) : i(1) {}
    int i;
  };
  constexpr volatile S vs;
```

reading from `vs.i` is not allowed, even though `i` is not volatile
qualified. Propagate the IsVolatile bit down the hierarchy, so we know
reading from `vs.i` is a volatile read.
2025-04-25 11:23:34 +02:00