1 //===--- InterpBuiltin.cpp - Interpreter for the constexpr VM ---*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 #include "Boolean.h"
9 #include "Interp.h"
10 #include "PrimType.h"
11 #include "clang/Basic/Builtins.h"
12 
13 namespace clang {
14 namespace interp {
15 
16 template <typename T> T getParam(InterpFrame *Frame, unsigned Index) {
17   unsigned Offset = Frame->getFunction()->getParamOffset(Index);
18   return Frame->getParam<T>(Offset);
19 }
20 
21 static bool interp__builtin_strcmp(InterpState &S, CodePtr OpPC,
22                                    InterpFrame *Frame) {
23   const Pointer &A = getParam<Pointer>(Frame, 0);
24   const Pointer &B = getParam<Pointer>(Frame, 1);
25 
26   if (!CheckLive(S, OpPC, A, AK_Read) || !CheckLive(S, OpPC, B, AK_Read))
27     return false;
28 
29   assert(A.getFieldDesc()->isPrimitiveArray());
30   assert(B.getFieldDesc()->isPrimitiveArray());
31 
32   unsigned IndexA = A.getIndex();
33   unsigned IndexB = B.getIndex();
34   int32_t Result = 0;
35   for (;; ++IndexA, ++IndexB) {
36     const Pointer &PA = A.atIndex(IndexA);
37     const Pointer &PB = B.atIndex(IndexB);
38     if (!CheckRange(S, OpPC, PA, AK_Read) ||
39         !CheckRange(S, OpPC, PB, AK_Read)) {
40       return false;
41     }
42     uint8_t CA = PA.deref<uint8_t>();
43     uint8_t CB = PB.deref<uint8_t>();
44 
45     if (CA > CB) {
46       Result = 1;
47       break;
48     } else if (CA < CB) {
49       Result = -1;
50       break;
51     }
52     if (CA == 0 || CB == 0)
53       break;
54   }
55 
56   S.Stk.push<Integral<32, true>>(Integral<32, true>::from(Result));
57   return true;
58 }
59 
60 bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F) {
61   InterpFrame *Frame = S.Current;
62   APValue Dummy;
63 
64   switch (F->getBuiltinID()) {
65   case Builtin::BI__builtin_is_constant_evaluated:
66     S.Stk.push<Boolean>(Boolean::from(S.inConstantContext()));
67     return Ret<PT_Bool, true>(S, OpPC, Dummy);
68   case Builtin::BI__builtin_assume:
69     return RetVoid<true>(S, OpPC, Dummy);
70   case Builtin::BI__builtin_strcmp:
71     if (interp__builtin_strcmp(S, OpPC, Frame))
72       return Ret<PT_Sint32, true>(S, OpPC, Dummy);
73     return false;
74   default:
75     return false;
76   }
77 
78   return false;
79 }
80 
81 } // namespace interp
82 } // namespace clang
83