[clang] 89e41e2 - [clang][Interp] Implement __builtin_complex
Timm Bäder via cfe-commits
cfe-commits at lists.llvm.org
Mon Mar 4 08:16:02 PST 2024
Author: Timm Bäder
Date: 2024-03-04T17:15:42+01:00
New Revision: 89e41e2965b2b38a4aa1ad7757684566679ef762
URL: https://github.com/llvm/llvm-project/commit/89e41e2965b2b38a4aa1ad7757684566679ef762
DIFF: https://github.com/llvm/llvm-project/commit/89e41e2965b2b38a4aa1ad7757684566679ef762.diff
LOG: [clang][Interp] Implement __builtin_complex
Added:
Modified:
clang/lib/AST/Interp/ByteCodeExprGen.cpp
clang/lib/AST/Interp/InterpBuiltin.cpp
clang/test/AST/Interp/complex.cpp
Removed:
################################################################################
diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
index b4110d5856d512..efe10458f77906 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -2730,6 +2730,18 @@ bool ByteCodeExprGen<Emitter>::VisitBuiltinCallExpr(const CallExpr *E) {
if (!Func)
return false;
+ QualType ReturnType = E->getType();
+ std::optional<PrimType> ReturnT = classify(E);
+
+ // Non-primitive return type. Prepare storage.
+ if (!Initializing && !ReturnT && !ReturnType->isVoidType()) {
+ std::optional<unsigned> LocalIndex = allocateLocal(E, /*IsExtended=*/false);
+ if (!LocalIndex)
+ return false;
+ if (!this->emitGetPtrLocal(*LocalIndex, E))
+ return false;
+ }
+
if (!Func->isUnevaluatedBuiltin()) {
// Put arguments on the stack.
for (const auto *Arg : E->arguments()) {
@@ -2741,10 +2753,9 @@ bool ByteCodeExprGen<Emitter>::VisitBuiltinCallExpr(const CallExpr *E) {
if (!this->emitCallBI(Func, E, E))
return false;
- QualType ReturnType = E->getCallReturnType(Ctx.getASTContext());
if (DiscardResult && !ReturnType->isVoidType()) {
- PrimType T = classifyPrim(ReturnType);
- return this->emitPop(T, E);
+ assert(ReturnT);
+ return this->emitPop(*ReturnT, E);
}
return true;
diff --git a/clang/lib/AST/Interp/InterpBuiltin.cpp b/clang/lib/AST/Interp/InterpBuiltin.cpp
index cc457ce41af595..5250d02be85a61 100644
--- a/clang/lib/AST/Interp/InterpBuiltin.cpp
+++ b/clang/lib/AST/Interp/InterpBuiltin.cpp
@@ -900,6 +900,25 @@ static bool interp__builtin_atomic_lock_free(InterpState &S, CodePtr OpPC,
return false;
}
+/// __builtin_complex(Float A, float B);
+static bool interp__builtin_complex(InterpState &S, CodePtr OpPC,
+ const InterpFrame *Frame,
+ const Function *Func,
+ const CallExpr *Call) {
+ const Floating &Arg2 = S.Stk.peek<Floating>();
+ const Floating &Arg1 = S.Stk.peek<Floating>(align(primSize(PT_Float)) * 2);
+ Pointer &Result = S.Stk.peek<Pointer>(align(primSize(PT_Float)) * 2 +
+ align(primSize(PT_Ptr)));
+
+ Result.atIndex(0).deref<Floating>() = Arg1;
+ Result.atIndex(0).initialize();
+ Result.atIndex(1).deref<Floating>() = Arg2;
+ Result.atIndex(1).initialize();
+ Result.initialize();
+
+ return true;
+}
+
bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
const CallExpr *Call) {
InterpFrame *Frame = S.Current;
@@ -907,9 +926,6 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
std::optional<PrimType> ReturnT = S.getContext().classify(Call);
- // If classify failed, we assume void.
- assert(ReturnT || Call->getType()->isVoidType());
-
switch (F->getBuiltinID()) {
case Builtin::BI__builtin_is_constant_evaluated:
S.Stk.push<Boolean>(Boolean::from(S.inConstantContext()));
@@ -1206,6 +1222,11 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
return false;
break;
+ case Builtin::BI__builtin_complex:
+ if (!interp__builtin_complex(S, OpPC, Frame, F, Call))
+ return false;
+ break;
+
default:
S.FFDiag(S.Current->getLocation(OpPC),
diag::note_invalid_subexpr_in_const_expr)
diff --git a/clang/test/AST/Interp/complex.cpp b/clang/test/AST/Interp/complex.cpp
index b6091d90867a01..8acce7b734d85a 100644
--- a/clang/test/AST/Interp/complex.cpp
+++ b/clang/test/AST/Interp/complex.cpp
@@ -1,8 +1,5 @@
-// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify -Wno-unused-value %s
-// RUN: %clang_cc1 -verify=ref -Wno-unused-value %s
-
-// expected-no-diagnostics
-// ref-no-diagnostics
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify=both,expected -Wno-unused-value %s
+// RUN: %clang_cc1 -verify=both,ref -Wno-unused-value %s
constexpr _Complex double z1 = {1.0, 2.0};
static_assert(__real(z1) == 1.0, "");
@@ -256,3 +253,16 @@ namespace DeclRefCopy {
}
static_assert(localComplexArray() == (24 + 42), "");
}
+
+namespace Builtin {
+ constexpr _Complex float A = __builtin_complex(10.0f, 20.0f);
+ static_assert(__real(A) == 10, "");
+ static_assert(__imag(A) == 20, "");
+
+ constexpr _Complex double B = __builtin_complex(10.0, 20.0);
+ static_assert(__real(B) == 10, "");
+ static_assert(__imag(B) == 20, "");
+
+
+ constexpr _Complex float C = __builtin_complex(10.0f, 20.0); // both-error {{arguments are of
diff erent types}}
+}
More information about the cfe-commits
mailing list