[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