tbaeder updated this revision to Diff 479201.
tbaeder added a comment.

Split `CallBI` out from `Call`, so we don't need special cases in 
`CheckCallable` etc. for builtin functions.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D137487/new/

https://reviews.llvm.org/D137487

Files:
  clang/lib/AST/CMakeLists.txt
  clang/lib/AST/Interp/ByteCodeExprGen.cpp
  clang/lib/AST/Interp/ByteCodeExprGen.h
  clang/lib/AST/Interp/Function.h
  clang/lib/AST/Interp/Interp.h
  clang/lib/AST/Interp/InterpBuiltin.cpp
  clang/lib/AST/Interp/Opcodes.td
  clang/test/AST/Interp/builtins.cpp

Index: clang/test/AST/Interp/builtins.cpp
===================================================================
--- /dev/null
+++ clang/test/AST/Interp/builtins.cpp
@@ -0,0 +1,24 @@
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter %s -verify
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter %s -S -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -verify=ref %s -Wno-constant-evaluated
+// RUN: %clang_cc1 -verify=ref %s -Wno-constant-evaluated %s -S -emit-llvm -o - | FileCheck %s
+
+// expected-no-diagnostics
+// ref-no-diagnostics
+
+using size_t = decltype(sizeof(int));
+
+namespace std {
+inline constexpr bool is_constant_evaluated() noexcept {
+  return __builtin_is_constant_evaluated();
+}
+} // namespace std
+
+constexpr bool b = std::is_constant_evaluated();
+static_assert(b, "");
+static_assert(std::is_constant_evaluated() , "");
+
+
+bool is_this_constant() {
+  return __builtin_is_constant_evaluated(); // CHECK: ret i1 false
+}
Index: clang/lib/AST/Interp/Opcodes.td
===================================================================
--- clang/lib/AST/Interp/Opcodes.td
+++ clang/lib/AST/Interp/Opcodes.td
@@ -165,6 +165,12 @@
   let ChangesPC = 1;
 }
 
+def CallBI : Opcode {
+  let Args = [ArgFunction];
+  let Types = [];
+  let ChangesPC = 1;
+}
+
 //===----------------------------------------------------------------------===//
 // Frame management
 //===----------------------------------------------------------------------===//
Index: clang/lib/AST/Interp/InterpBuiltin.cpp
===================================================================
--- /dev/null
+++ clang/lib/AST/Interp/InterpBuiltin.cpp
@@ -0,0 +1,51 @@
+//===--- InterpBuiltin.cpp - Interpreter for the constexpr VM ---*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#include "Boolean.h"
+#include "Interp.h"
+#include "PrimType.h"
+#include "clang/Basic/Builtins.h"
+
+namespace clang {
+namespace interp {
+
+/// This is a slightly simplified version of the Ret() we have in Interp.cpp
+/// If they end up diverging in the future, we should get rid of the code
+/// duplication.
+template <PrimType Name, class T = typename PrimConv<Name>::T>
+static bool Ret(InterpState &S, CodePtr &PC) {
+  S.CallStackDepth--;
+  const T &Ret = S.Stk.pop<T>();
+
+  assert(S.Current->getFrameOffset() == S.Stk.size() && "Invalid frame");
+  if (!S.checkingPotentialConstantExpression())
+    S.Current->popArgs();
+
+  InterpFrame *Caller = S.Current->Caller;
+  assert(Caller);
+
+  PC = S.Current->getRetPC();
+  delete S.Current;
+  S.Current = Caller;
+  S.Stk.push<T>(Ret);
+
+  return true;
+}
+
+bool InterpretBuiltin(InterpState &S, CodePtr PC, unsigned BuiltinID) {
+  switch (BuiltinID) {
+  case Builtin::BI__builtin_is_constant_evaluated:
+    S.Stk.push<Boolean>(Boolean::from(S.inConstantContext()));
+    Ret<PT_Bool>(S, PC);
+    return true;
+  }
+
+  return false;
+}
+
+} // namespace interp
+} // namespace clang
Index: clang/lib/AST/Interp/Interp.h
===================================================================
--- clang/lib/AST/Interp/Interp.h
+++ clang/lib/AST/Interp/Interp.h
@@ -105,6 +105,8 @@
 /// Interpreter entry point.
 bool Interpret(InterpState &S, APValue &Result);
 
+bool InterpretBuiltin(InterpState &S, CodePtr PC, unsigned BuiltinID);
+
 enum class ArithOp { Add, Sub };
 
 //===----------------------------------------------------------------------===//
@@ -1303,6 +1305,20 @@
   return false;
 }
 
+inline bool CallBI(InterpState &S, CodePtr &PC, const Function *Func) {
+  auto NewFrame = std::make_unique<InterpFrame>(S, Func, PC);
+
+  InterpFrame *FrameBefore = S.Current;
+  S.Current = NewFrame.get();
+
+  if (InterpretBuiltin(S, PC, Func->getBuiltinID())) {
+    NewFrame.release();
+    return true;
+  }
+  S.Current = FrameBefore;
+  return false;
+}
+
 //===----------------------------------------------------------------------===//
 // Read opcode arguments
 //===----------------------------------------------------------------------===//
Index: clang/lib/AST/Interp/Function.h
===================================================================
--- clang/lib/AST/Interp/Function.h
+++ clang/lib/AST/Interp/Function.h
@@ -138,6 +138,8 @@
   // Checks if the funtion already has a body attached.
   bool hasBody() const { return HasBody; }
 
+  unsigned getBuiltinID() const { return F->getBuiltinID(); }
+
   unsigned getNumParams() const { return ParamTypes.size(); }
 
 private:
Index: clang/lib/AST/Interp/ByteCodeExprGen.h
===================================================================
--- clang/lib/AST/Interp/ByteCodeExprGen.h
+++ clang/lib/AST/Interp/ByteCodeExprGen.h
@@ -67,6 +67,7 @@
   bool VisitPointerArithBinOp(const BinaryOperator *E);
   bool VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *E);
   bool VisitCallExpr(const CallExpr *E);
+  bool VisitBuiltinCallExpr(const CallExpr *E);
   bool VisitCXXMemberCallExpr(const CXXMemberCallExpr *E);
   bool VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *E);
   bool VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *E);
Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp
===================================================================
--- clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -1311,9 +1311,35 @@
   return false;
 }
 
+template <class Emitter>
+bool ByteCodeExprGen<Emitter>::VisitBuiltinCallExpr(const CallExpr *E) {
+  const Function *Func = getFunction(E->getDirectCallee());
+  if (!Func)
+    return false;
+
+  // Put arguments on the stack.
+  for (const auto *Arg : E->arguments()) {
+    if (!this->visit(Arg))
+      return false;
+  }
+
+  if (!this->emitCallBI(Func, E))
+    return false;
+
+  if (DiscardResult) {
+    QualType ReturnType = E->getCallReturnType(Ctx.getASTContext());
+    PrimType T = classifyPrim(ReturnType);
+
+    return this->emitPop(T, E);
+  }
+
+  return true;
+}
+
 template <class Emitter>
 bool ByteCodeExprGen<Emitter>::VisitCallExpr(const CallExpr *E) {
-  assert(!E->getBuiltinCallee() && "Builtin functions aren't supported yet");
+  if (E->getBuiltinCallee())
+    return VisitBuiltinCallExpr(E);
 
   const Decl *Callee = E->getCalleeDecl();
   if (const auto *FuncDecl = dyn_cast_or_null<FunctionDecl>(Callee)) {
@@ -1347,9 +1373,9 @@
         return false;
     }
 
-    // In any case call the function. The return value will end up on the stack and
-    // if the function has RVO, we already have the pointer on the stack to write
-    // the result into.
+    // In any case call the function. The return value will end up on the stack
+    // and if the function has RVO, we already have the pointer on the stack to
+    // write the result into.
     if (!this->emitCall(Func, E))
       return false;
 
Index: clang/lib/AST/CMakeLists.txt
===================================================================
--- clang/lib/AST/CMakeLists.txt
+++ clang/lib/AST/CMakeLists.txt
@@ -72,6 +72,7 @@
   Interp/EvalEmitter.cpp
   Interp/Frame.cpp
   Interp/Function.cpp
+  Interp/InterpBuiltin.cpp
   Interp/Interp.cpp
   Interp/InterpBlock.cpp
   Interp/InterpFrame.cpp
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to