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}} +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits