Skip to content

Commit 89e41e2

Browse files
committed
[clang][Interp] Implement __builtin_complex
1 parent f010b1b commit 89e41e2

File tree

3 files changed

+53
-11
lines changed

3 files changed

+53
-11
lines changed

clang/lib/AST/Interp/ByteCodeExprGen.cpp

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2730,6 +2730,18 @@ bool ByteCodeExprGen<Emitter>::VisitBuiltinCallExpr(const CallExpr *E) {
27302730
if (!Func)
27312731
return false;
27322732

2733+
QualType ReturnType = E->getType();
2734+
std::optional<PrimType> ReturnT = classify(E);
2735+
2736+
// Non-primitive return type. Prepare storage.
2737+
if (!Initializing && !ReturnT && !ReturnType->isVoidType()) {
2738+
std::optional<unsigned> LocalIndex = allocateLocal(E, /*IsExtended=*/false);
2739+
if (!LocalIndex)
2740+
return false;
2741+
if (!this->emitGetPtrLocal(*LocalIndex, E))
2742+
return false;
2743+
}
2744+
27332745
if (!Func->isUnevaluatedBuiltin()) {
27342746
// Put arguments on the stack.
27352747
for (const auto *Arg : E->arguments()) {
@@ -2741,10 +2753,9 @@ bool ByteCodeExprGen<Emitter>::VisitBuiltinCallExpr(const CallExpr *E) {
27412753
if (!this->emitCallBI(Func, E, E))
27422754
return false;
27432755

2744-
QualType ReturnType = E->getCallReturnType(Ctx.getASTContext());
27452756
if (DiscardResult && !ReturnType->isVoidType()) {
2746-
PrimType T = classifyPrim(ReturnType);
2747-
return this->emitPop(T, E);
2757+
assert(ReturnT);
2758+
return this->emitPop(*ReturnT, E);
27482759
}
27492760

27502761
return true;

clang/lib/AST/Interp/InterpBuiltin.cpp

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -900,16 +900,32 @@ static bool interp__builtin_atomic_lock_free(InterpState &S, CodePtr OpPC,
900900
return false;
901901
}
902902

903+
/// __builtin_complex(Float A, float B);
904+
static bool interp__builtin_complex(InterpState &S, CodePtr OpPC,
905+
const InterpFrame *Frame,
906+
const Function *Func,
907+
const CallExpr *Call) {
908+
const Floating &Arg2 = S.Stk.peek<Floating>();
909+
const Floating &Arg1 = S.Stk.peek<Floating>(align(primSize(PT_Float)) * 2);
910+
Pointer &Result = S.Stk.peek<Pointer>(align(primSize(PT_Float)) * 2 +
911+
align(primSize(PT_Ptr)));
912+
913+
Result.atIndex(0).deref<Floating>() = Arg1;
914+
Result.atIndex(0).initialize();
915+
Result.atIndex(1).deref<Floating>() = Arg2;
916+
Result.atIndex(1).initialize();
917+
Result.initialize();
918+
919+
return true;
920+
}
921+
903922
bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
904923
const CallExpr *Call) {
905924
InterpFrame *Frame = S.Current;
906925
APValue Dummy;
907926

908927
std::optional<PrimType> ReturnT = S.getContext().classify(Call);
909928

910-
// If classify failed, we assume void.
911-
assert(ReturnT || Call->getType()->isVoidType());
912-
913929
switch (F->getBuiltinID()) {
914930
case Builtin::BI__builtin_is_constant_evaluated:
915931
S.Stk.push<Boolean>(Boolean::from(S.inConstantContext()));
@@ -1206,6 +1222,11 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
12061222
return false;
12071223
break;
12081224

1225+
case Builtin::BI__builtin_complex:
1226+
if (!interp__builtin_complex(S, OpPC, Frame, F, Call))
1227+
return false;
1228+
break;
1229+
12091230
default:
12101231
S.FFDiag(S.Current->getLocation(OpPC),
12111232
diag::note_invalid_subexpr_in_const_expr)

clang/test/AST/Interp/complex.cpp

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
1-
// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify -Wno-unused-value %s
2-
// RUN: %clang_cc1 -verify=ref -Wno-unused-value %s
3-
4-
// expected-no-diagnostics
5-
// ref-no-diagnostics
1+
// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify=both,expected -Wno-unused-value %s
2+
// RUN: %clang_cc1 -verify=both,ref -Wno-unused-value %s
63

74
constexpr _Complex double z1 = {1.0, 2.0};
85
static_assert(__real(z1) == 1.0, "");
@@ -256,3 +253,16 @@ namespace DeclRefCopy {
256253
}
257254
static_assert(localComplexArray() == (24 + 42), "");
258255
}
256+
257+
namespace Builtin {
258+
constexpr _Complex float A = __builtin_complex(10.0f, 20.0f);
259+
static_assert(__real(A) == 10, "");
260+
static_assert(__imag(A) == 20, "");
261+
262+
constexpr _Complex double B = __builtin_complex(10.0, 20.0);
263+
static_assert(__real(B) == 10, "");
264+
static_assert(__imag(B) == 20, "");
265+
266+
267+
constexpr _Complex float C = __builtin_complex(10.0f, 20.0); // both-error {{arguments are of different types}}
268+
}

0 commit comments

Comments
 (0)