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