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