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