HLSL constant sized array function parameters do not decay to pointers.
Instead constant sized array types are preserved as unique types for
overload resolution, template instantiation and name mangling.
This implements the change by adding a new `ArrayParameterType` which
represents a non-decaying `ConstantArrayType`. The new type behaves the
same as `ConstantArrayType` except that it does not decay to a pointer.
Values of `ConstantArrayType` in HLSL decay during overload resolution
via a new `HLSLArrayRValue` cast to `ArrayParameterType`.
`ArrayParamterType` values are passed indirectly by-value to functions
in IR generation resulting in callee generated memcpy instructions.
The behavior of HLSL function calls is documented in the [draft language
specification](https://microsoft.github.io/hlsl-specs/specs/hlsl.pdf)
under the Expr.Post.Call heading.
Additionally the design of this implementation approach is documented in
[Clang's
documentation](https://clang.llvm.org/docs/HLSL/FunctionCalls.html)
Resolves#70123
To authenticate pointers, CodeGen needs access to the key and
discriminators that were used to sign the pointer. That information is
sometimes known from the context, but not always, which is why `Address`
needs to hold that information.
This patch adds methods and data members to `Address`, which will be
needed in subsequent patches to authenticate signed pointers, and uses
the newly added methods throughout CodeGen. Although this patch isn't
strictly NFC as it causes CodeGen to use different code paths in some
cases (e.g., `mergeAddressesInConditionalExpr`), it doesn't cause any
changes in functionality as it doesn't add any information needed for
authentication.
In addition to the changes mentioned above, this patch introduces class
`RawAddress`, which contains a pointer that we know is unsigned, and
adds several new functions for creating `Address` and `LValue` objects.
This reapplies d9a685a9dd589486e882b722e513ee7b8c84870c, which was
reverted because it broke ubsan bots. There seems to be a bug in
coroutine code-gen, which is causing EmitTypeCheck to use the wrong
alignment. For now, pass alignment zero to EmitTypeCheck so that it can
compute the correct alignment based on the passed type (see function
EmitCXXMemberOrOperatorMemberCallExpr).
To authenticate pointers, CodeGen needs access to the key and
discriminators that were used to sign the pointer. That information is
sometimes known from the context, but not always, which is why `Address`
needs to hold that information.
This patch adds methods and data members to `Address`, which will be
needed in subsequent patches to authenticate signed pointers, and uses
the newly added methods throughout CodeGen. Although this patch isn't
strictly NFC as it causes CodeGen to use different code paths in some
cases (e.g., `mergeAddressesInConditionalExpr`), it doesn't cause any
changes in functionality as it doesn't add any information needed for
authentication.
In addition to the changes mentioned above, this patch introduces class
`RawAddress`, which contains a pointer that we know is unsigned, and
adds several new functions for creating `Address` and `LValue` objects.
This reapplies 8bd1f9116aab879183f34707e6d21c7051d083b6. The commit
broke msan bots because LValue::IsKnownNonNull was uninitialized.
In PR #79382, I need to add a new type that derives from
ConstantArrayType. This means that ConstantArrayType can no longer use
`llvm::TrailingObjects` to store the trailing optional Expr*.
This change refactors ConstantArrayType to store a 60-bit integer and
4-bits for the integer size in bytes. This replaces the APInt field
previously in the type but preserves enough information to recreate it
where needed.
To reduce the number of places where the APInt is re-constructed I've
also added some helper methods to the ConstantArrayType to allow some
common use cases that operate on either the stored small integer or the
APInt as appropriate.
Resolves#85124.
To authenticate pointers, CodeGen needs access to the key and
discriminators that were used to sign the pointer. That information is
sometimes known from the context, but not always, which is why `Address`
needs to hold that information.
This patch adds methods and data members to `Address`, which will be
needed in subsequent patches to authenticate signed pointers, and uses
the newly added methods throughout CodeGen. Although this patch isn't
strictly NFC as it causes CodeGen to use different code paths in some
cases (e.g., `mergeAddressesInConditionalExpr`), it doesn't cause any
changes in functionality as it doesn't add any information needed for
authentication.
In addition to the changes mentioned above, this patch introduces class
`RawAddress`, which contains a pointer that we know is unsigned, and
adds several new functions for creating `Address` and `LValue` objects.
HLSL supports vector truncation and element conversions as part of
standard conversion sequences. The vector truncation conversion is a C++
second conversion in the conversion sequence. If a vector truncation is
in a conversion sequence an element conversion may occur after it before
the standard C++ third conversion.
Vector element conversions can be boolean conversions, floating point or
integral conversions or promotions.
[HLSL Draft
Specification](https://microsoft.github.io/hlsl-specs/specs/hlsl.pdf)
---------
Co-authored-by: Aaron Ballman <aaron@aaronballman.com>
Implements https://isocpp.org/files/papers/P2662R3.pdf
The feature is exposed as an extension in older language modes.
Mangling is not yet supported and that is something we will have to do before release.
Turned out we were making overly simple assumptions about which sections (& section flags) would be used when emitting a global into a custom section. This lead to sections with read-only flags being used for globals of struct types with mutable members.
Fixed by porting the codegen function with the more nuanced handling/checking for mutable members out of codegen for use in the sema code that does this initial checking/mapping to section flags.
Differential Revision: https://reviews.llvm.org/D156726
Consider the following statements:
long x = 1;
short y = 1;
With the following AST:
|-VarDecl 0x55d289973730 <x.c:1:1, col:10> col:6 x 'long' cinit
| `-ImplicitCastExpr 0x55d289973800 <col:10> 'long' <IntegralCast>
| `-IntegerLiteral 0x55d2899737e0 <col:10> 'int' 1
`-VarDecl 0x55d289973830 <line:2:1, col:11> col:7 y 'short' cinit
`-ImplicitCastExpr 0x55d2899738b8 <col:11> 'short' <IntegralCast>
`-IntegerLiteral 0x55d289973898 <col:11> 'int' 1
Sign or Zero extend or truncate based on the source signedness and
destination width.
Reviewed By: efriedma
Differential Revision: https://reviews.llvm.org/D156466
Consider the statement:
int x = -1;
And the following AST:
`-VarDecl 0x55c4823a7670 <x.c:2:1, col:10> col:5 x 'int' cinit
`-UnaryOperator 0x55c4823a7740 <col:9, col:10> 'int' prefix '-'
`-IntegerLiteral 0x55c4823a7720 <col:10> 'int' 1
Return the evaluation of the subexpression negated.
Reviewed By: efriedma
Differential Revision: https://reviews.llvm.org/D156378
Consider the following statement:
void* foo = ((void *)0);
For the sub-AST:
| `-ImplicitCastExpr 'const void *' <NullToPointer>
| `-CStyleCastExpr 'void *' <NullToPointer>
| `-IntegerLiteral 'int' 0
If the subexpression of the cast is itself the NULL constant, then
ImplicitCastExpr should emit the NULL pointer constant.
Reviewed By: efriedma
Differential Revision: https://reviews.llvm.org/D156175
Consider the following statement:
const char* foo = "foo";
For the sub-AST:
`-ImplicitCastExpr <col:19> 'const char *' <NoOp>
`-ImplicitCastExpr <col:19> 'char *' <ArrayToPointerDecay>
`-StringLiteral <col:19> 'char[4]' lvalue "foo"
The address of the StringLiteral can be emitted as the Constant.
Reviewed By: efriedma
Differential Revision: https://reviews.llvm.org/D156185
Improves the ability of ConstExprEmitter to evaluate constants.
Found by adding asserts to ConstantEmitter::tryEmitPrivate to find cases
where ConstExprEmitter::Visit() fails to resolve (obvious) constants.
Reviewed By: efriedma
Differential Revision: https://reviews.llvm.org/D156154
As suggested by @efriedma in:
https://reviews.llvm.org/D76096#4370369
This should speed up evaluating whether an expression is constant or
not, but due to the complexity of these two different implementations,
we may start getting different answers for edge cases for which we do
not yet have test cases in-tree (or perhaps even performance regressions
for some cases). As such, contributors have carte blanche to revert if
necessary.
For additional historical context about ExprConstant vs CGExprConstant,
here's snippets from a private conversation on discord:
ndesaulniers:
why do we have clang/lib/AST/ExprConstant.cpp and
clang/lib/CodeGen/CGExprConstant.cpp? Does clang constant fold during
ast walking/creation AND during LLVM codegen?
efriedma:
originally, clang needed to handle two things: integer constant
expressions (the "5" in "int x[5];"), and constant global initializers
(the "5" in "int x = 5;"). pre-C++11, the two could be handled mostly
separately; so we had the code for integer constants in AST/, and the
code for globals in CodeGen/. C++11 constexpr sort of destroyed that
separation, though. so now we do both kinds of constant evaluation on
the AST, then CGExprConstant translates the result of that evaluation
to LLVM IR. but we kept around some bits of the old cgexprconstant to
avoid performance/memory usage regressions on large arrays.
Reviewed By: efriedma
Differential Revision: https://reviews.llvm.org/D151587
Partial progress towards replacing in-tree uses of `Type::getPointerTo()`.
This needs to be done before deprecating the API.
Reviewed By: nikic, barannikov88
Differential Revision: https://reviews.llvm.org/D152321
Reported by Static Code Analyzer Tool:
Inside "CGExprConstant.cpp" file, VisitObjCEncodeExpr() returns null value which is dereferenced without checking.
This patch adds an assert.
Reviewed By: erichkeane
Differential Revision: https://reviews.llvm.org/D151280
flexible array member
A zero-element array type was incorrectly being used when an incomplete
array was being initialized with a non-empty initializer.
This fixes an assertion failure in AddInitializerToStaticVarDecl. See
the discussion here: https://reviews.llvm.org/D123649#4362210
Differential Revision: https://reviews.llvm.org/D151172
This follows 2b4fa53 which made Clang not emit destructor calls for such
objects. However, they would still not get emitted as constants since
CodeGenModule::isTypeConstant() returns false if the destructor is
constexpr. This change adds a param to make isTypeConstant() ignore the
dtor, allowing the caller to check it instead.
Fixes Issue #61212
Differential revision: https://reviews.llvm.org/D145369
This patch mechanically replaces None with std::nullopt where the
compiler would warn if None were deprecated. The intent is to reduce
the amount of manual work required in migrating from Optional to
std::optional.
This is part of an effort to migrate from llvm::Optional to
std::optional:
https://discourse.llvm.org/t/deprecating-llvm-optional-x-hasvalue-getvalue-getvalueor/63716
This patch fixes a crash when trying to emit a constant compound literal.
For C++ Clang evaluates either casts or binary operations at translation time,
but doesn't pass on the InConstantContext information that was inferred when
parsing the statement. Because of this, strict FP evaluation (-ftrapping-math)
which shouldn't be in effect yet, then causes checkFloatingpointResult to return
false, which in tryEmitGlobalCompoundLiteral will trigger an assert that the
compound literal wasn't constant.
The discussion here around 'manifestly constant evaluated contexts' was very
helpful to me when trying to understand what LLVM's position is on what
evaluation context should be in effect, together with the explanatory text in
that patch itself:
https://reviews.llvm.org/D87528
Reviewed By: rjmccall, DavidSpickett
Differential Revision: https://reviews.llvm.org/D131555
Clang currently crashes when lowering a consteval list initialization
of a temporary. This is partially working around an issue in the
template instantiation code (TreeTransform::TransformCXXTemporaryObjectExpr())
that does not yet know how to handle list initialization of temporaries
in all cases. However, it's also helping reduce fragility by ensuring
we always have a valid QualType when trying to emit a constant
expression during IR generation.
Fixes#55871
Differential Revision: https://reviews.llvm.org/D131194
If a zero-sized field has a non-trivial initializer, it should prevent
the overall struct initialization from being folded to a constant during
IR generation. Don't just ignore zero-sized fields entirely in IR
constant emission.
In D123649, I got the formula for getFlexibleArrayInitChars slightly
wrong: the flexible array elements can be contained in the tail padding
of the struct. Fix the formula to account for that.
With the fixed formula, we run into another issue: in some cases, we
were emitting extra padding for flexible arrray initializers. Fix
CGExprConstant so it uses a packed struct when necessary, to avoid this
extra padding.
Differential Revision: https://reviews.llvm.org/D123826
We were generating wrong code for cxx20-consteval-crash.cpp: instead of
loading a value of a variable, we were using its address as the
initializer.
Found while adding code to verify the size of constant initializers.
Differential Revision: https://reviews.llvm.org/D123648
This builtin returns the address of a global instance of the
`std::source_location::__impl` type, which must be defined (with an
appropriate shape) before calling the builtin.
It will be used to implement std::source_location in libc++ in a
future change. The builtin is compatible with GCC's implementation,
and libstdc++'s usage. An intentional divergence is that GCC declares
the builtin's return type to be `const void*` (for
ease-of-implementation reasons), while Clang uses the actual type,
`const std::source_location::__impl*`.
In order to support this new functionality, I've also added a new
'UnnamedGlobalConstantDecl'. This artificial Decl is modeled after
MSGuidDecl, and is used to represent a generic concept of an lvalue
constant with global scope, deduplicated by its value. It's possible
that MSGuidDecl itself, or some of the other similar sorts of things
in Clang might be able to be refactored onto this more-generic
concept, but there's enough special-case weirdness in MSGuidDecl that
I gave up attempting to share code there, at least for now.
Finally, for compatibility with libstdc++'s <source_location> header,
I've added a second exception to the "cannot cast from void* to T* in
constant evaluation" rule. This seems a bit distasteful, but feels
like the best available option.
Reviewers: aaron.ballman, erichkeane
Differential Revision: https://reviews.llvm.org/D120159
ConstStructBuilder::Finalize in CGExprConstant.ccp assumes that the
passed in QualType is a RecordType. In some instances, the type is a
reference to a RecordType and the reference needs to be removed first.
Differential Revision: https://reviews.llvm.org/D117376
Control-Flow Integrity (CFI) replaces references to address-taken
functions with pointers to the CFI jump table. This is a problem
for low-level code, such as operating system kernels, which may
need the address of an actual function body without the jump table
indirection.
This change adds the __builtin_function_start() builtin, which
accepts an argument that can be constant-evaluated to a function,
and returns the address of the function body.
Link: https://github.com/ClangBuiltLinux/linux/issues/1353
Depends on D108478
Reviewed By: pcc, rjmccall
Differential Revision: https://reviews.llvm.org/D108479
Change all uses of the deprecated constructor to pass the
element type explicitly and drop it.
For cases where the correct element type was not immediately
obvious to me or would require a slightly larger change I'm
falling back to explicitly calling getPointerElementType() for now.