Skip to content

[clang][bytecode] Use bitcasts to cast from integer to vector #117547

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 21 additions & 2 deletions clang/lib/AST/ByteCode/Compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,10 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {

QualType SubExprTy = SubExpr->getType();
std::optional<PrimType> FromT = classify(SubExprTy);
// Casts from integer to vectors in C.
if (FromT && CE->getType()->isVectorType())
return this->emitBuiltinBitCast(CE);

std::optional<PrimType> ToT = classify(CE->getType());
if (!FromT || !ToT)
return false;
Expand Down Expand Up @@ -6494,8 +6498,23 @@ bool Compiler<Emitter>::emitBuiltinBitCast(const CastExpr *E) {
}

// Get a pointer to the value-to-cast on the stack.
if (!this->visit(SubExpr))
return false;
// For CK_LValueToRValueBitCast, this is always an lvalue and
// we later assume it to be one (i.e. a PT_Ptr). However,
// we call this function for other utility methods where
// a bitcast might be useful, so convert it to a PT_Ptr in that case.
if (SubExpr->isGLValue()) {
if (!this->visit(SubExpr))
return false;
} else if (std::optional<PrimType> FromT = classify(SubExpr)) {
unsigned TempOffset = allocateLocalPrimitive(
SubExpr, *FromT, /*IsConst=*/true, /*IsExtended=*/false);
if (!this->visit(SubExpr))
return false;
if (!this->emitSetLocal(*FromT, TempOffset, E))
return false;
if (!this->emitGetPtrLocal(TempOffset, E))
return false;
}

if (!ToT || ToT == PT_Ptr) {
if (!this->emitBitCastPtr(E))
Expand Down
26 changes: 25 additions & 1 deletion clang/test/AST/ByteCode/c23.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
// RUN: %clang_cc1 -std=c23 -fexperimental-new-constant-interpreter -verify=expected,both %s
// RUN: %clang_cc1 -std=c23 -verify=ref,both %s
// RUN: %clang_cc1 -std=c23 -triple=aarch64_be-linux-gnu -fexperimental-new-constant-interpreter -verify=expected,both %s
// RUN: %clang_cc1 -std=c23 -triple=aarch64_be-linux-gnu -verify=ref,both %s


typedef typeof(nullptr) nullptr_t;

Expand All @@ -23,5 +26,26 @@ char bar() {
return ((struct S *)buffer)->c;
}


static_assert((nullptr_t){} == 0);

#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
# define LITTLE_END 1
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
# define LITTLE_END 0
#else
# error "huh?"
#endif

typedef unsigned char u8x4_t __attribute__((vector_size(4)));
constexpr u8x4_t arg1 = (u8x4_t)0xCAFEBABE; // okay
#if LITTLE_END
static_assert(arg1[0] == 190);
static_assert(arg1[1] == 186);
static_assert(arg1[2] == 254);
static_assert(arg1[3] == 202);
#else
static_assert(arg1[0] == 202);
static_assert(arg1[1] == 254);
static_assert(arg1[2] == 186);
static_assert(arg1[3] == 190);
#endif
Loading