50 Commits

Author SHA1 Message Date
Timm Baeder
3cd0bb7f67
[clang][bytecode] Check evaluate{String,Strlen} for pointer type (#180524)
We can only use block pointers here.
2026-02-09 16:02:53 +01:00
Timm Baeder
4344268ad6
[clang] Return std::optional from all Expr::tryEvaluate* API (#179230)
tryEvaluateString was returning an std::optional, but the other try* API
was not. Update tryEvaluateObjectSize and tryEvaluateStrLen to return an
std::optional<uint64_t>.
2026-02-09 13:37:14 +01:00
Timm Baeder
d368773249
[clang][bytecode] Use in Expr::tryEvaluateObjectSize() (#179197)
This is like https://github.com/llvm/llvm-project/pull/179033, which
broke a few builders for reasons I still don't really understand. I ran
the other clang tests and this version fixes a few of the introduced
regressions.

This still regresses `CodeGen/pass-object-size.c`, but that's a
pre-existing issue.

Patch is of coursed based on #179033 by @mariusdr.
2026-02-02 14:03:13 +01:00
marius doerner
8e7a2d8b42
Revert "[clang][bytecode] Use in Expr::tryEvaluateObjectSize (#1790… (#179099)
…33)"

This reverts commit 756c321c33af2be0bd40707948aae3c06163a0a6.

Test failure in clang/test/AST/ByteCode/builtins.c in CI build

CC @tbaederr
2026-02-01 12:34:09 +01:00
marius doerner
756c321c33
[clang][bytecode] Use in Expr::tryEvaluateObjectSize (#179033)
Fixes #138474

Use new bytecode intepreter in `Expr::tryEvaluateObjectSize`. Reuses the
already existing implementation for `__builtin_object_size` in of the
intepreter.

---------

Co-authored-by: Timm Baeder <tbaeder@redhat.com>
2026-02-01 10:08:42 +01:00
Timm Baeder
afb2e4f2e2
[clang][bytecode] Clean up interp::Function parameter handling (#178621)
Replace the multiple data structures with a vector + a map holding all
`ParamDescriptor`s. Update docs.
2026-01-30 10:07:23 +01:00
Timm Baeder
0d562c9668
[clang][bytecode] Only check static lambda captures if we have to (#178452)
Call `getCaptureFields()` only if the function is static, because we
only care about the captures in that case.
2026-01-29 06:16:25 +01:00
Oliver Hunt
c0f4a8a7fc
[clang][bytecode] Fix incorrect handling of arithmetic on string literals (#173212)
The fast path for string literals fails to consider the offset of the
pointer into an array of chars, this change simply adds the required
checks and bounds corrections prior to calling strnlen.

Fixes #173175
2025-12-24 00:30:17 -08:00
Sean Perry
8fce476c81
Implement a more seamless way to provide missing functions on z/OS (#167703)
In this PR I'm changing the way we provide the missing functions like
strnlen() on z/OS from the separate header file to a wrapper around the
system headers that declare these functions. This will be less
intrusive.

---------

Co-authored-by: Zibi Sarbinowski <zibi@ca.ibm.com>
2025-11-18 15:58:39 -05:00
Timm Baeder
c8c5a382a2
[clang][bytecode] Move shared interp functions to InterpHelpers.h (#164215)
This drastically reduces the preprocessed size of Context.cpp and
InterpBuiltin.cpp.
2025-10-21 14:25:59 +02:00
Timm Baeder
c332952ed0
[clang][bytecode] Check param types against function prototype (#163920)
If the type of the ParmVarDecl and the parameter type from the
FunctionProtoType don't match, we're in for trouble. Just reject those
functions.

Fixes #163568
2025-10-20 17:14:04 +02:00
Timm Baeder
c750487292
[clang][bytecode] Diagnose volatile writes (#160350) 2025-09-28 07:21:40 +02:00
Timm Baeder
f9305c900b
[clang][bytecode] Use in Expr::tryEvaluateString (#160118)
Fixes #157492
2025-09-25 07:50:38 +02:00
Zibi Sarbinowski
55f230f74e
[z.OS] fix strnlen() usage in Context.cpp available on z/OS (#160339)
On z/OS `strnlen()` is not available by default so we use the wrapper
header `zOSSupport.h` to make it visible. This will fix the following
error:

```
clang/lib/AST/ByteCode/Context.cpp:250:16: error: use of undeclared identifier 'strnlen'
  250 |       Result = strnlen(reinterpret_cast<const char *>(Ptr.getRawAddress()), N);
      |                ^~~~~~~
1 error generated.
```
2025-09-23 14:08:20 -04:00
Osama Abdelkader
004e462682
[clang][bytecode] Fix unknown size arrays crash in clang bytecode (#160015)
Fixes #153948

Signed-off-by: Osama Abdelkader <osama.abdelkader@gmail.com>
2025-09-23 13:12:36 +00:00
Timm Baeder
68c9ddb930
[clang][bytecode] Typecheck called function pointers more thorougly (#159757)
Fix two older FIXME items from the `functions.cpp` test.
2025-09-19 14:24:48 +02:00
Timm Baeder
03e16c8e42
[clang][bytecode] Move generic lambda handling to Compiler (#159733)
So the static invoker's Function still points to the static invoker
instead of the call operator of the lambda record. This is important for
a later commit.
2025-09-19 12:51:02 +02:00
Timm Baeder
03c356c554
[clang][bytecode] Pass initializer along in evaluateAsInitializer() (#158056)
We just called `getInit()`, which isn't always correct and used the
wrong initializer in the module test case.
2025-09-15 07:39:11 +02:00
Timm Baeder
168308325d
[clang][bytecode] Simplify and optimize EvaluationResult (#155772)
Remove support for saving a `Pointer` in the `EvaluationResult` since
that was unused. Add `stealAPValue()` which moves the `APValue` out of
the `EvaluationResult` to avoid a copy at the end of the evaluation.
2025-08-28 10:06:04 +02:00
Matheus Izvekov
2ec71d93ad
[clang] NFC: introduce Type::getAsEnumDecl, and cast variants for all TagDecls (#155463)
And make use of those.

These changes are split from prior PR #155028, in order to decrease the
size of that PR and facilitate review.
2025-08-26 16:05:59 -03:00
Timm Baeder
6ce13ae1c2
[clang][bytecode] Always track item types in InterpStack (#151088)
This has been a long-standing problem, but we didn't use to call the
destructors of items on the stack unless we explicitly `pop()` or
`discard()` them.

When interpretation was interrupted midway-through (because something
failed), we left `Pointer`s on the stack. Since all `Block`s track what
`Pointer`s point to them (via a doubly-linked list in the `Pointer`),
that meant we potentially leave deallocated pointers in that list. We
used to work around this by removing the `Pointer` from the list before
deallocating the block.

However, we now want to track pointers to global blocks as well, which
poses a problem since the blocks are never deallocated and thus those
pointers are always left dangling.

I've tried a few different approaches to fixing this but in the end I
just gave up on the idea of never knowing what items are in the stack.
We already have an `ItemTypes` vector that we use for debugging
assertions. This patch simply enables this vector unconditionally and
uses it in the abort case to properly `discard()` all elements from the
stack. That's a little sad IMO but I don't know of another way of
solving this problem.

As expected, this is a slight hit to compile times:
https://llvm-compile-time-tracker.com/compare.php?from=574d0a92060bf4808776b7a0239ffe91a092b15d&to=0317105f559093cfb909bfb01857a6b837991940&stat=instructions:u
2025-08-18 17:15:31 +02:00
Timm Baeder
b9fef09e8e
[clang][bytecode] Add canClassify() helper (#152755)
Sometimes we don't need the return value of a classsify() call, we only
need to know if we can map the given Expr/Type to a primitive type. Add
canClassify() for that.
2025-08-09 15:08:14 +02:00
Matheus Izvekov
91cdd35008
[clang] Improve nested name specifier AST representation (#147835)
This is a major change on how we represent nested name qualifications in
the AST.

* The nested name specifier itself and how it's stored is changed. The
prefixes for types are handled within the type hierarchy, which makes
canonicalization for them super cheap, no memory allocation required.
Also translating a type into nested name specifier form becomes a no-op.
An identifier is stored as a DependentNameType. The nested name
specifier gains a lightweight handle class, to be used instead of
passing around pointers, which is similar to what is implemented for
TemplateName. There is still one free bit available, and this handle can
be used within a PointerUnion and PointerIntPair, which should keep
bit-packing aficionados happy.
* The ElaboratedType node is removed, all type nodes in which it could
previously apply to can now store the elaborated keyword and name
qualifier, tail allocating when present.
* TagTypes can now point to the exact declaration found when producing
these, as opposed to the previous situation of there only existing one
TagType per entity. This increases the amount of type sugar retained,
and can have several applications, for example in tracking module
ownership, and other tools which care about source file origins, such as
IWYU. These TagTypes are lazily allocated, in order to limit the
increase in AST size.

This patch offers a great performance benefit.

It greatly improves compilation time for
[stdexec](https://github.com/NVIDIA/stdexec). For one datapoint, for
`test_on2.cpp` in that project, which is the slowest compiling test,
this patch improves `-c` compilation time by about 7.2%, with the
`-fsyntax-only` improvement being at ~12%.

This has great results on compile-time-tracker as well:

![image](https://github.com/user-attachments/assets/700dce98-2cab-4aa8-97d1-b038c0bee831)

This patch also further enables other optimziations in the future, and
will reduce the performance impact of template specialization resugaring
when that lands.

It has some other miscelaneous drive-by fixes.

About the review: Yes the patch is huge, sorry about that. Part of the
reason is that I started by the nested name specifier part, before the
ElaboratedType part, but that had a huge performance downside, as
ElaboratedType is a big performance hog. I didn't have the steam to go
back and change the patch after the fact.

There is also a lot of internal API changes, and it made sense to remove
ElaboratedType in one go, versus removing it from one type at a time, as
that would present much more churn to the users. Also, the nested name
specifier having a different API avoids missing changes related to how
prefixes work now, which could make existing code compile but not work.

How to review: The important changes are all in
`clang/include/clang/AST` and `clang/lib/AST`, with also important
changes in `clang/lib/Sema/TreeTransform.h`.

The rest and bulk of the changes are mostly consequences of the changes
in API.

PS: TagType::getDecl is renamed to `getOriginalDecl` in this patch, just
for easier to rebasing. I plan to rename it back after this lands.

Fixes #136624
Fixes https://github.com/llvm/llvm-project/issues/43179
Fixes https://github.com/llvm/llvm-project/issues/68670
Fixes https://github.com/llvm/llvm-project/issues/92757
2025-08-09 05:06:53 -03:00
Timm Baeder
105963ad5e
[clang][bytecode] Use SmallVector for Function::Code (#151821)
This way we can use resize_for_overwrite, which is slightly more
efficient:

https://llvm-compile-time-tracker.com/compare.php?from=7bdab76350970a3ac471da6a30035dd5b7ef14f3&to=b55bd2c74f230e2150e54b0523db6a8426eab54d&stat=instructions:u
2025-08-04 17:03:58 +02:00
Kazu Hirata
39ca925ffe
[AST] Use llvm::iterator_range::empty (NFC) (#151904) 2025-08-04 07:40:38 -07:00
Timm Baeder
8259be65c7
[clang][bytecode] Remove unused includes (#151848)
UnsignedOrNone.h from PrimType.h and ASTLambda.h from Function.h.
2025-08-03 08:52:03 +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
5b0935f1f0
[clang][bytecode] Reintroduce Pointer::elem() (#149693)
As a way of writing atIndex(I).deref<T>(), which creates an intermediate
Pointer, which in turn adds (and removes) that pointer from the pointer
list of the Block. This way we can avoid that.
2025-07-20 10:59:50 +02:00
Timm Baeder
51af47e53c
[clang][bytecode] Use in Expr::tryEvaluateStrLen() (#149677)
Fixes #138475
2025-07-20 09:00:22 +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
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
478bdd8b90
[clang][bytecode] Save Constexpr bit in Function (#142793)
Rename isConstexpr to isValid, the former was always a bad name. Save a
constexpr bit in Function so we don't have to access the decl in
CheckCallable.
2025-06-05 06:38:48 +02:00
Timm Baeder
b36e161a09
[clang][bytecode][NFC] Cache more integer type sizes (#142720) 2025-06-04 10:07:48 +02:00
Timm Baeder
3c8a6bc3b7
[clang][bytecode] Optimize classify() further (#140735)
Try to do as few checks as possible. Check for builtin types only once,
then look at the BuiltinType Kind. For integers, we cache the int and
long size, since those are used a lot and the ASTContext::getIntWidth()
call is costly.
2025-05-21 07:35:00 +02:00
Timm Baeder
b26adacc85
[clang][bytecode] Check destructors for temporaries (#140039)
Also, increase the EvalID in isPotentialConstantExpr(), since this is
its own evaluation.
2025-05-15 14:34:35 +02:00
Timm Baeder
f7c01c4045
[clang][bytecode] Reorder type checks in classify() (#139046)
Move the member pointer check further below and remove Complex/Vector
type checks and instead rely on the final return to handle those.
2025-05-09 06:48:24 +02:00
Timm Baeder
ecc73a6f1c
[clang][bytecode] Use bytecode interpreter in EvaluateCharRangeAsString (#138461)
This was always using the ast walker.
2025-05-05 09:06:34 +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
02f923f8e4
[clang][bytecode] Classify function pointers as PT_Ptr (#135026)
The Pointer class already has the capability to be a function pointer,
but we still classifed function pointers as PT_FnPtr/FunctionPointer.
This means when converting from a Pointer to a FunctionPointer, we lost
the information of what the original Pointer pointed to.
2025-04-10 06:40:54 +02:00
Timm Baeder
83356f3b62
[clang][bytecode] Compile functions lazily (#131596)
Create the Function* handles for all functions we see, but delay the
actual compilation until we really call the function. This speeds up
compile times with the new interpreter a bit.
2025-03-17 15:58:35 +01:00
Timm Baeder
06130ed341
Reapply "[clang][bytecode] Stack-allocate bottom function frame" (#12… (#125349)
…5325)

Move the BottomFrame to InterpState instead.
2025-02-01 18:12:35 +01:00
Timm Baeder
2c934dc5e1
[clang][bytecode] Always compile most recent function decl (#124722) 2025-01-28 11:43:02 +01:00
Timm Baeder
82ed9c0319
[clang][bytecode][NFC] Remove APValue Result argument where unnecessary (#118199)
This is unneeded in almost all circumstances. We only return an APValue
back to clang when the evaluation is finished, and that is always done
by an EvalEmitter - which has its own implementation of the Ret
instructions.
2024-12-01 17:36:19 +01:00
Timm Baeder
3eaf4a9d1a
[clang][bytecode] Check for memory leaks after destroying global scope (#112868)
The global scope we create when evaluating expressions might free some
of the dynamic memory allocations, so we can't check for memory leaks
before destroying it.
2024-10-18 13:03:13 +02:00
Timm Baeder
048bc67276
[clang][bytecode] Start implementing fixed point types (#110216)
Add the primitive type and implement to-bool casts.
2024-09-27 11:32:43 +02:00
Timm Baeder
83fea8b809
[clang][bytecode] Allow continuing when discarded MemberExpr Base fails (#107231)
We don't need the value in this case, since we're discarding it anyway.
Allow continuing the interpretation but note the side effect.
2024-09-07 09:33:27 +02:00
Timm Baeder
eef8116be1
[clang][bytecode] Only visit local variables if they have constant init (#107576)
See the comment I added for why this is weird. We might want to have a
different mechanism for this in the future.

Fixes https://github.com/llvm/llvm-project/issues/101801
2024-09-07 06:36:21 +02:00
Timm Baeder
ca148b2150
[clang][bytecode] Support ObjC blocks (#104551)
I started out by adding a new pointer type for blocks, and I was fully
prepared to compile their AST to bytecode and later call them.

... then I found out that the current interpreter doesn't support
calling blocks at all. So we reuse `Function` to support sources other
than `FunctionDecl`s and classify `BlockPointerType` as `PT_FnPtr`.
2024-08-20 06:08:53 +02:00
Timm Baeder
f620c5b692
[clang][bytecode] Classify 1-bit unsigned integers as bool (#104662)
This happens for enum types with bool parent types. isBooleanType()
returns false for them however.

The previous version did the same thing by re-classifying the enum
integer type, but that breaks with forward-declared enums.
2024-08-17 22:06:46 +02:00
Timm Baeder
a07aba5d44
[clang] Rename all AST/Interp stuff to AST/ByteCode (#104552)
"Interp" clashes with the clang interpreter and people often confuse
this.
2024-08-16 17:13:12 +02:00