Interp.h 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309
  1. //===--- Interp.h - 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. //
  9. // Definition of the interpreter state and entry point.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #ifndef LLVM_CLANG_AST_INTERP_INTERP_H
  13. #define LLVM_CLANG_AST_INTERP_INTERP_H
  14. #include "Boolean.h"
  15. #include "Function.h"
  16. #include "InterpFrame.h"
  17. #include "InterpStack.h"
  18. #include "InterpState.h"
  19. #include "Opcode.h"
  20. #include "PrimType.h"
  21. #include "Program.h"
  22. #include "State.h"
  23. #include "clang/AST/ASTContext.h"
  24. #include "clang/AST/ASTDiagnostic.h"
  25. #include "clang/AST/CXXInheritance.h"
  26. #include "clang/AST/Expr.h"
  27. #include "llvm/ADT/APFloat.h"
  28. #include "llvm/ADT/APSInt.h"
  29. #include "llvm/Support/Endian.h"
  30. #include <limits>
  31. #include <type_traits>
  32. namespace clang {
  33. namespace interp {
  34. using APInt = llvm::APInt;
  35. using APSInt = llvm::APSInt;
  36. /// Convert a value to an APValue.
  37. template <typename T> bool ReturnValue(const T &V, APValue &R) {
  38. R = V.toAPValue();
  39. return true;
  40. }
  41. /// Checks if the variable has externally defined storage.
  42. bool CheckExtern(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
  43. /// Checks if the array is offsetable.
  44. bool CheckArray(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
  45. /// Checks if a pointer is live and accessible.
  46. bool CheckLive(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
  47. AccessKinds AK);
  48. /// Checks if a pointer is null.
  49. bool CheckNull(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
  50. CheckSubobjectKind CSK);
  51. /// Checks if a pointer is in range.
  52. bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
  53. AccessKinds AK);
  54. /// Checks if a field from which a pointer is going to be derived is valid.
  55. bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
  56. CheckSubobjectKind CSK);
  57. /// Checks if a pointer points to const storage.
  58. bool CheckConst(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
  59. /// Checks if a pointer points to a mutable field.
  60. bool CheckMutable(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
  61. /// Checks if a value can be loaded from a block.
  62. bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
  63. /// Checks if a value can be stored in a block.
  64. bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
  65. /// Checks if a method can be invoked on an object.
  66. bool CheckInvoke(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
  67. /// Checks if a value can be initialized.
  68. bool CheckInit(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
  69. /// Checks if a method can be called.
  70. bool CheckCallable(InterpState &S, CodePtr OpPC, const Function *F);
  71. /// Checks the 'this' pointer.
  72. bool CheckThis(InterpState &S, CodePtr OpPC, const Pointer &This);
  73. /// Checks if a method is pure virtual.
  74. bool CheckPure(InterpState &S, CodePtr OpPC, const CXXMethodDecl *MD);
  75. /// Checks that all fields are initialized after a constructor call.
  76. bool CheckCtorCall(InterpState &S, CodePtr OpPC, const Pointer &This);
  77. /// Checks if the shift operation is legal.
  78. template <typename RT>
  79. bool CheckShift(InterpState &S, CodePtr OpPC, const RT &RHS, unsigned Bits) {
  80. if (RHS.isNegative()) {
  81. const SourceInfo &Loc = S.Current->getSource(OpPC);
  82. S.CCEDiag(Loc, diag::note_constexpr_negative_shift) << RHS.toAPSInt();
  83. return false;
  84. }
  85. // C++11 [expr.shift]p1: Shift width must be less than the bit width of
  86. // the shifted type.
  87. if (Bits > 1 && RHS >= RT::from(Bits, RHS.bitWidth())) {
  88. const Expr *E = S.Current->getExpr(OpPC);
  89. const APSInt Val = RHS.toAPSInt();
  90. QualType Ty = E->getType();
  91. S.CCEDiag(E, diag::note_constexpr_large_shift) << Val << Ty << Bits;
  92. return false;
  93. }
  94. return true;
  95. }
  96. /// Checks if Div/Rem operation on LHS and RHS is valid.
  97. template <typename T>
  98. bool CheckDivRem(InterpState &S, CodePtr OpPC, const T &LHS, const T &RHS) {
  99. if (RHS.isZero()) {
  100. const SourceInfo &Loc = S.Current->getSource(OpPC);
  101. S.FFDiag(Loc, diag::note_expr_divide_by_zero);
  102. return false;
  103. }
  104. if (LHS.isSigned() && LHS.isMin() && RHS.isNegative() && RHS.isMinusOne()) {
  105. APSInt LHSInt = LHS.toAPSInt();
  106. SmallString<32> Trunc;
  107. (-LHSInt.extend(LHSInt.getBitWidth() + 1)).toString(Trunc, 10);
  108. const SourceInfo &Loc = S.Current->getSource(OpPC);
  109. const Expr *E = S.Current->getExpr(OpPC);
  110. S.CCEDiag(Loc, diag::note_constexpr_overflow) << Trunc << E->getType();
  111. return false;
  112. }
  113. return true;
  114. }
  115. /// Interpreter entry point.
  116. bool Interpret(InterpState &S, APValue &Result);
  117. //===----------------------------------------------------------------------===//
  118. // Add, Sub, Mul
  119. //===----------------------------------------------------------------------===//
  120. template <typename T, bool (*OpFW)(T, T, unsigned, T *),
  121. template <typename U> class OpAP>
  122. bool AddSubMulHelper(InterpState &S, CodePtr OpPC, unsigned Bits, const T &LHS,
  123. const T &RHS) {
  124. // Fast path - add the numbers with fixed width.
  125. T Result;
  126. if (!OpFW(LHS, RHS, Bits, &Result)) {
  127. S.Stk.push<T>(Result);
  128. return true;
  129. }
  130. // If for some reason evaluation continues, use the truncated results.
  131. S.Stk.push<T>(Result);
  132. // Slow path - compute the result using another bit of precision.
  133. APSInt Value = OpAP<APSInt>()(LHS.toAPSInt(Bits), RHS.toAPSInt(Bits));
  134. // Report undefined behaviour, stopping if required.
  135. const Expr *E = S.Current->getExpr(OpPC);
  136. QualType Type = E->getType();
  137. if (S.checkingForUndefinedBehavior()) {
  138. SmallString<32> Trunc;
  139. Value.trunc(Result.bitWidth()).toString(Trunc, 10);
  140. auto Loc = E->getExprLoc();
  141. S.report(Loc, diag::warn_integer_constant_overflow) << Trunc << Type;
  142. return true;
  143. } else {
  144. S.CCEDiag(E, diag::note_constexpr_overflow) << Value << Type;
  145. return S.noteUndefinedBehavior();
  146. }
  147. }
  148. template <PrimType Name, class T = typename PrimConv<Name>::T>
  149. bool Add(InterpState &S, CodePtr OpPC) {
  150. const T &RHS = S.Stk.pop<T>();
  151. const T &LHS = S.Stk.pop<T>();
  152. const unsigned Bits = RHS.bitWidth() + 1;
  153. return AddSubMulHelper<T, T::add, std::plus>(S, OpPC, Bits, LHS, RHS);
  154. }
  155. template <PrimType Name, class T = typename PrimConv<Name>::T>
  156. bool Sub(InterpState &S, CodePtr OpPC) {
  157. const T &RHS = S.Stk.pop<T>();
  158. const T &LHS = S.Stk.pop<T>();
  159. const unsigned Bits = RHS.bitWidth() + 1;
  160. return AddSubMulHelper<T, T::sub, std::minus>(S, OpPC, Bits, LHS, RHS);
  161. }
  162. template <PrimType Name, class T = typename PrimConv<Name>::T>
  163. bool Mul(InterpState &S, CodePtr OpPC) {
  164. const T &RHS = S.Stk.pop<T>();
  165. const T &LHS = S.Stk.pop<T>();
  166. const unsigned Bits = RHS.bitWidth() * 2;
  167. return AddSubMulHelper<T, T::mul, std::multiplies>(S, OpPC, Bits, LHS, RHS);
  168. }
  169. /// 1) Pops the RHS from the stack.
  170. /// 2) Pops the LHS from the stack.
  171. /// 3) Pushes 'LHS & RHS' on the stack
  172. template <PrimType Name, class T = typename PrimConv<Name>::T>
  173. bool BitAnd(InterpState &S, CodePtr OpPC) {
  174. const T &RHS = S.Stk.pop<T>();
  175. const T &LHS = S.Stk.pop<T>();
  176. unsigned Bits = RHS.bitWidth();
  177. T Result;
  178. if (!T::bitAnd(LHS, RHS, Bits, &Result)) {
  179. S.Stk.push<T>(Result);
  180. return true;
  181. }
  182. return false;
  183. }
  184. /// 1) Pops the RHS from the stack.
  185. /// 2) Pops the LHS from the stack.
  186. /// 3) Pushes 'LHS | RHS' on the stack
  187. template <PrimType Name, class T = typename PrimConv<Name>::T>
  188. bool BitOr(InterpState &S, CodePtr OpPC) {
  189. const T &RHS = S.Stk.pop<T>();
  190. const T &LHS = S.Stk.pop<T>();
  191. unsigned Bits = RHS.bitWidth();
  192. T Result;
  193. if (!T::bitOr(LHS, RHS, Bits, &Result)) {
  194. S.Stk.push<T>(Result);
  195. return true;
  196. }
  197. return false;
  198. }
  199. /// 1) Pops the RHS from the stack.
  200. /// 2) Pops the LHS from the stack.
  201. /// 3) Pushes 'LHS ^ RHS' on the stack
  202. template <PrimType Name, class T = typename PrimConv<Name>::T>
  203. bool BitXor(InterpState &S, CodePtr OpPC) {
  204. const T &RHS = S.Stk.pop<T>();
  205. const T &LHS = S.Stk.pop<T>();
  206. unsigned Bits = RHS.bitWidth();
  207. T Result;
  208. if (!T::bitXor(LHS, RHS, Bits, &Result)) {
  209. S.Stk.push<T>(Result);
  210. return true;
  211. }
  212. return false;
  213. }
  214. /// 1) Pops the RHS from the stack.
  215. /// 2) Pops the LHS from the stack.
  216. /// 3) Pushes 'LHS % RHS' on the stack (the remainder of dividing LHS by RHS).
  217. template <PrimType Name, class T = typename PrimConv<Name>::T>
  218. bool Rem(InterpState &S, CodePtr OpPC) {
  219. const T &RHS = S.Stk.pop<T>();
  220. const T &LHS = S.Stk.pop<T>();
  221. if (!CheckDivRem(S, OpPC, LHS, RHS))
  222. return false;
  223. const unsigned Bits = RHS.bitWidth() * 2;
  224. T Result;
  225. if (!T::rem(LHS, RHS, Bits, &Result)) {
  226. S.Stk.push<T>(Result);
  227. return true;
  228. }
  229. return false;
  230. }
  231. /// 1) Pops the RHS from the stack.
  232. /// 2) Pops the LHS from the stack.
  233. /// 3) Pushes 'LHS / RHS' on the stack
  234. template <PrimType Name, class T = typename PrimConv<Name>::T>
  235. bool Div(InterpState &S, CodePtr OpPC) {
  236. const T &RHS = S.Stk.pop<T>();
  237. const T &LHS = S.Stk.pop<T>();
  238. if (!CheckDivRem(S, OpPC, LHS, RHS))
  239. return false;
  240. const unsigned Bits = RHS.bitWidth() * 2;
  241. T Result;
  242. if (!T::div(LHS, RHS, Bits, &Result)) {
  243. S.Stk.push<T>(Result);
  244. return true;
  245. }
  246. return false;
  247. }
  248. //===----------------------------------------------------------------------===//
  249. // Inv
  250. //===----------------------------------------------------------------------===//
  251. template <PrimType Name, class T = typename PrimConv<Name>::T>
  252. bool Inv(InterpState &S, CodePtr OpPC) {
  253. using BoolT = PrimConv<PT_Bool>::T;
  254. const T &Val = S.Stk.pop<T>();
  255. const unsigned Bits = Val.bitWidth();
  256. Boolean R;
  257. Boolean::inv(BoolT::from(Val, Bits), &R);
  258. S.Stk.push<BoolT>(R);
  259. return true;
  260. }
  261. //===----------------------------------------------------------------------===//
  262. // Neg
  263. //===----------------------------------------------------------------------===//
  264. template <PrimType Name, class T = typename PrimConv<Name>::T>
  265. bool Neg(InterpState &S, CodePtr OpPC) {
  266. const T &Val = S.Stk.pop<T>();
  267. T Result;
  268. T::neg(Val, &Result);
  269. S.Stk.push<T>(Result);
  270. return true;
  271. }
  272. enum class PushVal : bool {
  273. No,
  274. Yes,
  275. };
  276. enum class IncDecOp {
  277. Inc,
  278. Dec,
  279. };
  280. template <typename T, IncDecOp Op, PushVal DoPush>
  281. bool IncDecHelper(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
  282. T Value = Ptr.deref<T>();
  283. T Result;
  284. if constexpr (DoPush == PushVal::Yes)
  285. S.Stk.push<T>(Result);
  286. if constexpr (Op == IncDecOp::Inc) {
  287. if (!T::increment(Value, &Result)) {
  288. Ptr.deref<T>() = Result;
  289. return true;
  290. }
  291. } else {
  292. if (!T::decrement(Value, &Result)) {
  293. Ptr.deref<T>() = Result;
  294. return true;
  295. }
  296. }
  297. // Something went wrong with the previous operation. Compute the
  298. // result with another bit of precision.
  299. unsigned Bits = Value.bitWidth() + 1;
  300. APSInt APResult;
  301. if constexpr (Op == IncDecOp::Inc)
  302. APResult = ++Value.toAPSInt(Bits);
  303. else
  304. APResult = --Value.toAPSInt(Bits);
  305. // Report undefined behaviour, stopping if required.
  306. const Expr *E = S.Current->getExpr(OpPC);
  307. QualType Type = E->getType();
  308. if (S.checkingForUndefinedBehavior()) {
  309. SmallString<32> Trunc;
  310. APResult.trunc(Result.bitWidth()).toString(Trunc, 10);
  311. auto Loc = E->getExprLoc();
  312. S.report(Loc, diag::warn_integer_constant_overflow) << Trunc << Type;
  313. return true;
  314. }
  315. S.CCEDiag(E, diag::note_constexpr_overflow) << APResult << Type;
  316. return S.noteUndefinedBehavior();
  317. }
  318. /// 1) Pops a pointer from the stack
  319. /// 2) Load the value from the pointer
  320. /// 3) Writes the value increased by one back to the pointer
  321. /// 4) Pushes the original (pre-inc) value on the stack.
  322. template <PrimType Name, class T = typename PrimConv<Name>::T>
  323. bool Inc(InterpState &S, CodePtr OpPC) {
  324. // FIXME: Check initialization of Ptr
  325. const Pointer &Ptr = S.Stk.pop<Pointer>();
  326. return IncDecHelper<T, IncDecOp::Inc, PushVal::Yes>(S, OpPC, Ptr);
  327. }
  328. /// 1) Pops a pointer from the stack
  329. /// 2) Load the value from the pointer
  330. /// 3) Writes the value increased by one back to the pointer
  331. template <PrimType Name, class T = typename PrimConv<Name>::T>
  332. bool IncPop(InterpState &S, CodePtr OpPC) {
  333. // FIXME: Check initialization of Ptr
  334. const Pointer &Ptr = S.Stk.pop<Pointer>();
  335. return IncDecHelper<T, IncDecOp::Inc, PushVal::No>(S, OpPC, Ptr);
  336. }
  337. /// 1) Pops a pointer from the stack
  338. /// 2) Load the value from the pointer
  339. /// 3) Writes the value decreased by one back to the pointer
  340. /// 4) Pushes the original (pre-dec) value on the stack.
  341. template <PrimType Name, class T = typename PrimConv<Name>::T>
  342. bool Dec(InterpState &S, CodePtr OpPC) {
  343. // FIXME: Check initialization of Ptr
  344. const Pointer &Ptr = S.Stk.pop<Pointer>();
  345. return IncDecHelper<T, IncDecOp::Dec, PushVal::Yes>(S, OpPC, Ptr);
  346. }
  347. /// 1) Pops a pointer from the stack
  348. /// 2) Load the value from the pointer
  349. /// 3) Writes the value decreased by one back to the pointer
  350. template <PrimType Name, class T = typename PrimConv<Name>::T>
  351. bool DecPop(InterpState &S, CodePtr OpPC) {
  352. // FIXME: Check initialization of Ptr
  353. const Pointer &Ptr = S.Stk.pop<Pointer>();
  354. return IncDecHelper<T, IncDecOp::Dec, PushVal::No>(S, OpPC, Ptr);
  355. }
  356. /// 1) Pops the value from the stack.
  357. /// 2) Pushes the bitwise complemented value on the stack (~V).
  358. template <PrimType Name, class T = typename PrimConv<Name>::T>
  359. bool Comp(InterpState &S, CodePtr OpPC) {
  360. const T &Val = S.Stk.pop<T>();
  361. T Result;
  362. if (!T::comp(Val, &Result)) {
  363. S.Stk.push<T>(Result);
  364. return true;
  365. }
  366. return false;
  367. }
  368. //===----------------------------------------------------------------------===//
  369. // EQ, NE, GT, GE, LT, LE
  370. //===----------------------------------------------------------------------===//
  371. using CompareFn = llvm::function_ref<bool(ComparisonCategoryResult)>;
  372. template <typename T>
  373. bool CmpHelper(InterpState &S, CodePtr OpPC, CompareFn Fn) {
  374. using BoolT = PrimConv<PT_Bool>::T;
  375. const T &RHS = S.Stk.pop<T>();
  376. const T &LHS = S.Stk.pop<T>();
  377. S.Stk.push<BoolT>(BoolT::from(Fn(LHS.compare(RHS))));
  378. return true;
  379. }
  380. template <typename T>
  381. bool CmpHelperEQ(InterpState &S, CodePtr OpPC, CompareFn Fn) {
  382. return CmpHelper<T>(S, OpPC, Fn);
  383. }
  384. template <>
  385. inline bool CmpHelper<Pointer>(InterpState &S, CodePtr OpPC, CompareFn Fn) {
  386. using BoolT = PrimConv<PT_Bool>::T;
  387. const Pointer &RHS = S.Stk.pop<Pointer>();
  388. const Pointer &LHS = S.Stk.pop<Pointer>();
  389. if (!Pointer::hasSameBase(LHS, RHS)) {
  390. const SourceInfo &Loc = S.Current->getSource(OpPC);
  391. S.FFDiag(Loc, diag::note_invalid_subexpr_in_const_expr);
  392. return false;
  393. } else {
  394. unsigned VL = LHS.getByteOffset();
  395. unsigned VR = RHS.getByteOffset();
  396. S.Stk.push<BoolT>(BoolT::from(Fn(Compare(VL, VR))));
  397. return true;
  398. }
  399. }
  400. template <>
  401. inline bool CmpHelperEQ<Pointer>(InterpState &S, CodePtr OpPC, CompareFn Fn) {
  402. using BoolT = PrimConv<PT_Bool>::T;
  403. const Pointer &RHS = S.Stk.pop<Pointer>();
  404. const Pointer &LHS = S.Stk.pop<Pointer>();
  405. if (LHS.isZero() && RHS.isZero()) {
  406. S.Stk.push<BoolT>(BoolT::from(Fn(ComparisonCategoryResult::Equal)));
  407. return true;
  408. }
  409. if (!Pointer::hasSameBase(LHS, RHS)) {
  410. S.Stk.push<BoolT>(BoolT::from(Fn(ComparisonCategoryResult::Unordered)));
  411. return true;
  412. } else {
  413. unsigned VL = LHS.getByteOffset();
  414. unsigned VR = RHS.getByteOffset();
  415. // In our Pointer class, a pointer to an array and a pointer to the first
  416. // element in the same array are NOT equal. They have the same Base value,
  417. // but a different Offset. This is a pretty rare case, so we fix this here
  418. // by comparing pointers to the first elements.
  419. if (LHS.inArray() && LHS.isRoot())
  420. VL = LHS.atIndex(0).getByteOffset();
  421. if (RHS.inArray() && RHS.isRoot())
  422. VR = RHS.atIndex(0).getByteOffset();
  423. S.Stk.push<BoolT>(BoolT::from(Fn(Compare(VL, VR))));
  424. return true;
  425. }
  426. }
  427. template <PrimType Name, class T = typename PrimConv<Name>::T>
  428. bool EQ(InterpState &S, CodePtr OpPC) {
  429. return CmpHelperEQ<T>(S, OpPC, [](ComparisonCategoryResult R) {
  430. return R == ComparisonCategoryResult::Equal;
  431. });
  432. }
  433. template <PrimType Name, class T = typename PrimConv<Name>::T>
  434. bool NE(InterpState &S, CodePtr OpPC) {
  435. return CmpHelperEQ<T>(S, OpPC, [](ComparisonCategoryResult R) {
  436. return R != ComparisonCategoryResult::Equal;
  437. });
  438. }
  439. template <PrimType Name, class T = typename PrimConv<Name>::T>
  440. bool LT(InterpState &S, CodePtr OpPC) {
  441. return CmpHelper<T>(S, OpPC, [](ComparisonCategoryResult R) {
  442. return R == ComparisonCategoryResult::Less;
  443. });
  444. }
  445. template <PrimType Name, class T = typename PrimConv<Name>::T>
  446. bool LE(InterpState &S, CodePtr OpPC) {
  447. return CmpHelper<T>(S, OpPC, [](ComparisonCategoryResult R) {
  448. return R == ComparisonCategoryResult::Less ||
  449. R == ComparisonCategoryResult::Equal;
  450. });
  451. }
  452. template <PrimType Name, class T = typename PrimConv<Name>::T>
  453. bool GT(InterpState &S, CodePtr OpPC) {
  454. return CmpHelper<T>(S, OpPC, [](ComparisonCategoryResult R) {
  455. return R == ComparisonCategoryResult::Greater;
  456. });
  457. }
  458. template <PrimType Name, class T = typename PrimConv<Name>::T>
  459. bool GE(InterpState &S, CodePtr OpPC) {
  460. return CmpHelper<T>(S, OpPC, [](ComparisonCategoryResult R) {
  461. return R == ComparisonCategoryResult::Greater ||
  462. R == ComparisonCategoryResult::Equal;
  463. });
  464. }
  465. //===----------------------------------------------------------------------===//
  466. // InRange
  467. //===----------------------------------------------------------------------===//
  468. template <PrimType Name, class T = typename PrimConv<Name>::T>
  469. bool InRange(InterpState &S, CodePtr OpPC) {
  470. const T RHS = S.Stk.pop<T>();
  471. const T LHS = S.Stk.pop<T>();
  472. const T Value = S.Stk.pop<T>();
  473. S.Stk.push<bool>(LHS <= Value && Value <= RHS);
  474. return true;
  475. }
  476. //===----------------------------------------------------------------------===//
  477. // Dup, Pop, Test
  478. //===----------------------------------------------------------------------===//
  479. template <PrimType Name, class T = typename PrimConv<Name>::T>
  480. bool Dup(InterpState &S, CodePtr OpPC) {
  481. S.Stk.push<T>(S.Stk.peek<T>());
  482. return true;
  483. }
  484. template <PrimType Name, class T = typename PrimConv<Name>::T>
  485. bool Pop(InterpState &S, CodePtr OpPC) {
  486. S.Stk.pop<T>();
  487. return true;
  488. }
  489. //===----------------------------------------------------------------------===//
  490. // Const
  491. //===----------------------------------------------------------------------===//
  492. template <PrimType Name, class T = typename PrimConv<Name>::T>
  493. bool Const(InterpState &S, CodePtr OpPC, const T &Arg) {
  494. S.Stk.push<T>(Arg);
  495. return true;
  496. }
  497. //===----------------------------------------------------------------------===//
  498. // Get/Set Local/Param/Global/This
  499. //===----------------------------------------------------------------------===//
  500. template <PrimType Name, class T = typename PrimConv<Name>::T>
  501. bool GetLocal(InterpState &S, CodePtr OpPC, uint32_t I) {
  502. const Pointer &Ptr = S.Current->getLocalPointer(I);
  503. if (!CheckLoad(S, OpPC, Ptr))
  504. return false;
  505. S.Stk.push<T>(Ptr.deref<T>());
  506. return true;
  507. }
  508. template <PrimType Name, class T = typename PrimConv<Name>::T>
  509. bool SetLocal(InterpState &S, CodePtr OpPC, uint32_t I) {
  510. S.Current->setLocal<T>(I, S.Stk.pop<T>());
  511. return true;
  512. }
  513. template <PrimType Name, class T = typename PrimConv<Name>::T>
  514. bool GetParam(InterpState &S, CodePtr OpPC, uint32_t I) {
  515. if (S.checkingPotentialConstantExpression()) {
  516. return false;
  517. }
  518. S.Stk.push<T>(S.Current->getParam<T>(I));
  519. return true;
  520. }
  521. template <PrimType Name, class T = typename PrimConv<Name>::T>
  522. bool SetParam(InterpState &S, CodePtr OpPC, uint32_t I) {
  523. S.Current->setParam<T>(I, S.Stk.pop<T>());
  524. return true;
  525. }
  526. /// 1) Peeks a pointer on the stack
  527. /// 2) Pushes the value of the pointer's field on the stack
  528. template <PrimType Name, class T = typename PrimConv<Name>::T>
  529. bool GetField(InterpState &S, CodePtr OpPC, uint32_t I) {
  530. const Pointer &Obj = S.Stk.peek<Pointer>();
  531. if (!CheckNull(S, OpPC, Obj, CSK_Field))
  532. return false;
  533. if (!CheckRange(S, OpPC, Obj, CSK_Field))
  534. return false;
  535. const Pointer &Field = Obj.atField(I);
  536. if (!CheckLoad(S, OpPC, Field))
  537. return false;
  538. S.Stk.push<T>(Field.deref<T>());
  539. return true;
  540. }
  541. template <PrimType Name, class T = typename PrimConv<Name>::T>
  542. bool SetField(InterpState &S, CodePtr OpPC, uint32_t I) {
  543. const T &Value = S.Stk.pop<T>();
  544. const Pointer &Obj = S.Stk.peek<Pointer>();
  545. if (!CheckNull(S, OpPC, Obj, CSK_Field))
  546. return false;
  547. if (!CheckRange(S, OpPC, Obj, CSK_Field))
  548. return false;
  549. const Pointer &Field = Obj.atField(I);
  550. if (!CheckStore(S, OpPC, Field))
  551. return false;
  552. Field.deref<T>() = Value;
  553. return true;
  554. }
  555. /// 1) Pops a pointer from the stack
  556. /// 2) Pushes the value of the pointer's field on the stack
  557. template <PrimType Name, class T = typename PrimConv<Name>::T>
  558. bool GetFieldPop(InterpState &S, CodePtr OpPC, uint32_t I) {
  559. const Pointer &Obj = S.Stk.pop<Pointer>();
  560. if (!CheckNull(S, OpPC, Obj, CSK_Field))
  561. return false;
  562. if (!CheckRange(S, OpPC, Obj, CSK_Field))
  563. return false;
  564. const Pointer &Field = Obj.atField(I);
  565. if (!CheckLoad(S, OpPC, Field))
  566. return false;
  567. S.Stk.push<T>(Field.deref<T>());
  568. return true;
  569. }
  570. template <PrimType Name, class T = typename PrimConv<Name>::T>
  571. bool GetThisField(InterpState &S, CodePtr OpPC, uint32_t I) {
  572. if (S.checkingPotentialConstantExpression())
  573. return false;
  574. const Pointer &This = S.Current->getThis();
  575. if (!CheckThis(S, OpPC, This))
  576. return false;
  577. const Pointer &Field = This.atField(I);
  578. if (!CheckLoad(S, OpPC, Field))
  579. return false;
  580. S.Stk.push<T>(Field.deref<T>());
  581. return true;
  582. }
  583. template <PrimType Name, class T = typename PrimConv<Name>::T>
  584. bool SetThisField(InterpState &S, CodePtr OpPC, uint32_t I) {
  585. if (S.checkingPotentialConstantExpression())
  586. return false;
  587. const T &Value = S.Stk.pop<T>();
  588. const Pointer &This = S.Current->getThis();
  589. if (!CheckThis(S, OpPC, This))
  590. return false;
  591. const Pointer &Field = This.atField(I);
  592. if (!CheckStore(S, OpPC, Field))
  593. return false;
  594. Field.deref<T>() = Value;
  595. return true;
  596. }
  597. template <PrimType Name, class T = typename PrimConv<Name>::T>
  598. bool GetGlobal(InterpState &S, CodePtr OpPC, uint32_t I) {
  599. auto *B = S.P.getGlobal(I);
  600. if (B->isExtern())
  601. return false;
  602. S.Stk.push<T>(B->deref<T>());
  603. return true;
  604. }
  605. template <PrimType Name, class T = typename PrimConv<Name>::T>
  606. bool SetGlobal(InterpState &S, CodePtr OpPC, uint32_t I) {
  607. // TODO: emit warning.
  608. return false;
  609. }
  610. template <PrimType Name, class T = typename PrimConv<Name>::T>
  611. bool InitGlobal(InterpState &S, CodePtr OpPC, uint32_t I) {
  612. S.P.getGlobal(I)->deref<T>() = S.Stk.pop<T>();
  613. return true;
  614. }
  615. template <PrimType Name, class T = typename PrimConv<Name>::T>
  616. bool InitThisField(InterpState &S, CodePtr OpPC, uint32_t I) {
  617. if (S.checkingPotentialConstantExpression())
  618. return false;
  619. const Pointer &This = S.Current->getThis();
  620. if (!CheckThis(S, OpPC, This))
  621. return false;
  622. const Pointer &Field = This.atField(I);
  623. Field.deref<T>() = S.Stk.pop<T>();
  624. Field.initialize();
  625. return true;
  626. }
  627. template <PrimType Name, class T = typename PrimConv<Name>::T>
  628. bool InitThisBitField(InterpState &S, CodePtr OpPC, const Record::Field *F) {
  629. if (S.checkingPotentialConstantExpression())
  630. return false;
  631. const Pointer &This = S.Current->getThis();
  632. if (!CheckThis(S, OpPC, This))
  633. return false;
  634. const Pointer &Field = This.atField(F->Offset);
  635. const auto &Value = S.Stk.pop<T>();
  636. Field.deref<T>() = Value.truncate(F->Decl->getBitWidthValue(S.getCtx()));
  637. Field.initialize();
  638. return true;
  639. }
  640. template <PrimType Name, class T = typename PrimConv<Name>::T>
  641. bool InitThisFieldActive(InterpState &S, CodePtr OpPC, uint32_t I) {
  642. if (S.checkingPotentialConstantExpression())
  643. return false;
  644. const Pointer &This = S.Current->getThis();
  645. if (!CheckThis(S, OpPC, This))
  646. return false;
  647. const Pointer &Field = This.atField(I);
  648. Field.deref<T>() = S.Stk.pop<T>();
  649. Field.activate();
  650. Field.initialize();
  651. return true;
  652. }
  653. /// 1) Pops the value from the stack
  654. /// 2) Peeks a pointer from the stack
  655. /// 3) Pushes the value to field I of the pointer on the stack
  656. template <PrimType Name, class T = typename PrimConv<Name>::T>
  657. bool InitField(InterpState &S, CodePtr OpPC, uint32_t I) {
  658. const T &Value = S.Stk.pop<T>();
  659. const Pointer &Field = S.Stk.peek<Pointer>().atField(I);
  660. Field.deref<T>() = Value;
  661. Field.activate();
  662. Field.initialize();
  663. return true;
  664. }
  665. template <PrimType Name, class T = typename PrimConv<Name>::T>
  666. bool InitBitField(InterpState &S, CodePtr OpPC, const Record::Field *F) {
  667. const T &Value = S.Stk.pop<T>();
  668. const Pointer &Field = S.Stk.pop<Pointer>().atField(F->Offset);
  669. Field.deref<T>() = Value.truncate(F->Decl->getBitWidthValue(S.getCtx()));
  670. Field.activate();
  671. Field.initialize();
  672. return true;
  673. }
  674. template <PrimType Name, class T = typename PrimConv<Name>::T>
  675. bool InitFieldActive(InterpState &S, CodePtr OpPC, uint32_t I) {
  676. const T &Value = S.Stk.pop<T>();
  677. const Pointer &Ptr = S.Stk.pop<Pointer>();
  678. const Pointer &Field = Ptr.atField(I);
  679. Field.deref<T>() = Value;
  680. Field.activate();
  681. Field.initialize();
  682. return true;
  683. }
  684. //===----------------------------------------------------------------------===//
  685. // GetPtr Local/Param/Global/Field/This
  686. //===----------------------------------------------------------------------===//
  687. inline bool GetPtrLocal(InterpState &S, CodePtr OpPC, uint32_t I) {
  688. S.Stk.push<Pointer>(S.Current->getLocalPointer(I));
  689. return true;
  690. }
  691. inline bool GetPtrParam(InterpState &S, CodePtr OpPC, uint32_t I) {
  692. if (S.checkingPotentialConstantExpression()) {
  693. return false;
  694. }
  695. S.Stk.push<Pointer>(S.Current->getParamPointer(I));
  696. return true;
  697. }
  698. inline bool GetPtrGlobal(InterpState &S, CodePtr OpPC, uint32_t I) {
  699. S.Stk.push<Pointer>(S.P.getPtrGlobal(I));
  700. return true;
  701. }
  702. /// 1) Pops a Pointer from the stack
  703. /// 2) Pushes Pointer.atField(Off) on the stack
  704. inline bool GetPtrField(InterpState &S, CodePtr OpPC, uint32_t Off) {
  705. const Pointer &Ptr = S.Stk.pop<Pointer>();
  706. if (!CheckNull(S, OpPC, Ptr, CSK_Field))
  707. return false;
  708. if (!CheckExtern(S, OpPC, Ptr))
  709. return false;
  710. if (!CheckRange(S, OpPC, Ptr, CSK_Field))
  711. return false;
  712. S.Stk.push<Pointer>(Ptr.atField(Off));
  713. return true;
  714. }
  715. inline bool GetPtrThisField(InterpState &S, CodePtr OpPC, uint32_t Off) {
  716. if (S.checkingPotentialConstantExpression())
  717. return false;
  718. const Pointer &This = S.Current->getThis();
  719. if (!CheckThis(S, OpPC, This))
  720. return false;
  721. S.Stk.push<Pointer>(This.atField(Off));
  722. return true;
  723. }
  724. inline bool GetPtrActiveField(InterpState &S, CodePtr OpPC, uint32_t Off) {
  725. const Pointer &Ptr = S.Stk.pop<Pointer>();
  726. if (!CheckNull(S, OpPC, Ptr, CSK_Field))
  727. return false;
  728. if (!CheckRange(S, OpPC, Ptr, CSK_Field))
  729. return false;
  730. Pointer Field = Ptr.atField(Off);
  731. Ptr.deactivate();
  732. Field.activate();
  733. S.Stk.push<Pointer>(std::move(Field));
  734. return true;
  735. }
  736. inline bool GetPtrActiveThisField(InterpState &S, CodePtr OpPC, uint32_t Off) {
  737. if (S.checkingPotentialConstantExpression())
  738. return false;
  739. const Pointer &This = S.Current->getThis();
  740. if (!CheckThis(S, OpPC, This))
  741. return false;
  742. Pointer Field = This.atField(Off);
  743. This.deactivate();
  744. Field.activate();
  745. S.Stk.push<Pointer>(std::move(Field));
  746. return true;
  747. }
  748. inline bool GetPtrBase(InterpState &S, CodePtr OpPC, uint32_t Off) {
  749. const Pointer &Ptr = S.Stk.pop<Pointer>();
  750. if (!CheckNull(S, OpPC, Ptr, CSK_Base))
  751. return false;
  752. S.Stk.push<Pointer>(Ptr.atField(Off));
  753. return true;
  754. }
  755. inline bool GetPtrThisBase(InterpState &S, CodePtr OpPC, uint32_t Off) {
  756. if (S.checkingPotentialConstantExpression())
  757. return false;
  758. const Pointer &This = S.Current->getThis();
  759. if (!CheckThis(S, OpPC, This))
  760. return false;
  761. S.Stk.push<Pointer>(This.atField(Off));
  762. return true;
  763. }
  764. inline bool VirtBaseHelper(InterpState &S, CodePtr OpPC, const RecordDecl *Decl,
  765. const Pointer &Ptr) {
  766. Pointer Base = Ptr;
  767. while (Base.isBaseClass())
  768. Base = Base.getBase();
  769. auto *Field = Base.getRecord()->getVirtualBase(Decl);
  770. S.Stk.push<Pointer>(Base.atField(Field->Offset));
  771. return true;
  772. }
  773. inline bool GetPtrVirtBase(InterpState &S, CodePtr OpPC, const RecordDecl *D) {
  774. const Pointer &Ptr = S.Stk.pop<Pointer>();
  775. if (!CheckNull(S, OpPC, Ptr, CSK_Base))
  776. return false;
  777. return VirtBaseHelper(S, OpPC, D, Ptr);
  778. }
  779. inline bool GetPtrThisVirtBase(InterpState &S, CodePtr OpPC,
  780. const RecordDecl *D) {
  781. if (S.checkingPotentialConstantExpression())
  782. return false;
  783. const Pointer &This = S.Current->getThis();
  784. if (!CheckThis(S, OpPC, This))
  785. return false;
  786. return VirtBaseHelper(S, OpPC, D, S.Current->getThis());
  787. }
  788. //===----------------------------------------------------------------------===//
  789. // Load, Store, Init
  790. //===----------------------------------------------------------------------===//
  791. template <PrimType Name, class T = typename PrimConv<Name>::T>
  792. bool Load(InterpState &S, CodePtr OpPC) {
  793. const Pointer &Ptr = S.Stk.peek<Pointer>();
  794. if (!CheckLoad(S, OpPC, Ptr))
  795. return false;
  796. S.Stk.push<T>(Ptr.deref<T>());
  797. return true;
  798. }
  799. template <PrimType Name, class T = typename PrimConv<Name>::T>
  800. bool LoadPop(InterpState &S, CodePtr OpPC) {
  801. const Pointer &Ptr = S.Stk.pop<Pointer>();
  802. if (!CheckLoad(S, OpPC, Ptr))
  803. return false;
  804. S.Stk.push<T>(Ptr.deref<T>());
  805. return true;
  806. }
  807. template <PrimType Name, class T = typename PrimConv<Name>::T>
  808. bool Store(InterpState &S, CodePtr OpPC) {
  809. const T &Value = S.Stk.pop<T>();
  810. const Pointer &Ptr = S.Stk.peek<Pointer>();
  811. if (!CheckStore(S, OpPC, Ptr))
  812. return false;
  813. if (!Ptr.isRoot())
  814. Ptr.initialize();
  815. Ptr.deref<T>() = Value;
  816. return true;
  817. }
  818. template <PrimType Name, class T = typename PrimConv<Name>::T>
  819. bool StorePop(InterpState &S, CodePtr OpPC) {
  820. const T &Value = S.Stk.pop<T>();
  821. const Pointer &Ptr = S.Stk.pop<Pointer>();
  822. if (!CheckStore(S, OpPC, Ptr))
  823. return false;
  824. if (!Ptr.isRoot())
  825. Ptr.initialize();
  826. Ptr.deref<T>() = Value;
  827. return true;
  828. }
  829. template <PrimType Name, class T = typename PrimConv<Name>::T>
  830. bool StoreBitField(InterpState &S, CodePtr OpPC) {
  831. const T &Value = S.Stk.pop<T>();
  832. const Pointer &Ptr = S.Stk.peek<Pointer>();
  833. if (!CheckStore(S, OpPC, Ptr))
  834. return false;
  835. if (!Ptr.isRoot())
  836. Ptr.initialize();
  837. if (auto *FD = Ptr.getField()) {
  838. Ptr.deref<T>() = Value.truncate(FD->getBitWidthValue(S.getCtx()));
  839. } else {
  840. Ptr.deref<T>() = Value;
  841. }
  842. return true;
  843. }
  844. template <PrimType Name, class T = typename PrimConv<Name>::T>
  845. bool StoreBitFieldPop(InterpState &S, CodePtr OpPC) {
  846. const T &Value = S.Stk.pop<T>();
  847. const Pointer &Ptr = S.Stk.pop<Pointer>();
  848. if (!CheckStore(S, OpPC, Ptr))
  849. return false;
  850. if (!Ptr.isRoot())
  851. Ptr.initialize();
  852. if (auto *FD = Ptr.getField()) {
  853. Ptr.deref<T>() = Value.truncate(FD->getBitWidthValue(S.getCtx()));
  854. } else {
  855. Ptr.deref<T>() = Value;
  856. }
  857. return true;
  858. }
  859. template <PrimType Name, class T = typename PrimConv<Name>::T>
  860. bool InitPop(InterpState &S, CodePtr OpPC) {
  861. const T &Value = S.Stk.pop<T>();
  862. const Pointer &Ptr = S.Stk.pop<Pointer>();
  863. if (!CheckInit(S, OpPC, Ptr))
  864. return false;
  865. Ptr.initialize();
  866. new (&Ptr.deref<T>()) T(Value);
  867. return true;
  868. }
  869. /// 1) Pops the value from the stack
  870. /// 2) Peeks a pointer and gets its index \Idx
  871. /// 3) Sets the value on the pointer, leaving the pointer on the stack.
  872. template <PrimType Name, class T = typename PrimConv<Name>::T>
  873. bool InitElem(InterpState &S, CodePtr OpPC, uint32_t Idx) {
  874. const T &Value = S.Stk.pop<T>();
  875. const Pointer &Ptr = S.Stk.peek<Pointer>().atIndex(Idx);
  876. if (!CheckInit(S, OpPC, Ptr))
  877. return false;
  878. Ptr.initialize();
  879. new (&Ptr.deref<T>()) T(Value);
  880. return true;
  881. }
  882. /// The same as InitElem, but pops the pointer as well.
  883. template <PrimType Name, class T = typename PrimConv<Name>::T>
  884. bool InitElemPop(InterpState &S, CodePtr OpPC, uint32_t Idx) {
  885. const T &Value = S.Stk.pop<T>();
  886. const Pointer &Ptr = S.Stk.pop<Pointer>().atIndex(Idx);
  887. if (!CheckInit(S, OpPC, Ptr))
  888. return false;
  889. Ptr.initialize();
  890. new (&Ptr.deref<T>()) T(Value);
  891. return true;
  892. }
  893. //===----------------------------------------------------------------------===//
  894. // AddOffset, SubOffset
  895. //===----------------------------------------------------------------------===//
  896. template <class T, bool Add> bool OffsetHelper(InterpState &S, CodePtr OpPC) {
  897. // Fetch the pointer and the offset.
  898. const T &Offset = S.Stk.pop<T>();
  899. const Pointer &Ptr = S.Stk.pop<Pointer>();
  900. if (!CheckRange(S, OpPC, Ptr, CSK_ArrayToPointer))
  901. return false;
  902. // A zero offset does not change the pointer.
  903. if (Offset.isZero()) {
  904. S.Stk.push<Pointer>(Ptr);
  905. return true;
  906. }
  907. if (!CheckNull(S, OpPC, Ptr, CSK_ArrayIndex))
  908. return false;
  909. // Arrays of unknown bounds cannot have pointers into them.
  910. if (!CheckArray(S, OpPC, Ptr))
  911. return false;
  912. // Get a version of the index comparable to the type.
  913. T Index = T::from(Ptr.getIndex(), Offset.bitWidth());
  914. // Compute the largest index into the array.
  915. unsigned MaxIndex = Ptr.getNumElems();
  916. // Helper to report an invalid offset, computed as APSInt.
  917. auto InvalidOffset = [&]() {
  918. const unsigned Bits = Offset.bitWidth();
  919. APSInt APOffset(Offset.toAPSInt().extend(Bits + 2), false);
  920. APSInt APIndex(Index.toAPSInt().extend(Bits + 2), false);
  921. APSInt NewIndex = Add ? (APIndex + APOffset) : (APIndex - APOffset);
  922. S.CCEDiag(S.Current->getSource(OpPC), diag::note_constexpr_array_index)
  923. << NewIndex
  924. << /*array*/ static_cast<int>(!Ptr.inArray())
  925. << static_cast<unsigned>(MaxIndex);
  926. return false;
  927. };
  928. unsigned MaxOffset = MaxIndex - Ptr.getIndex();
  929. if constexpr (Add) {
  930. // If the new offset would be negative, bail out.
  931. if (Offset.isNegative() && (Offset.isMin() || -Offset > Index))
  932. return InvalidOffset();
  933. // If the new offset would be out of bounds, bail out.
  934. if (Offset.isPositive() && Offset > MaxOffset)
  935. return InvalidOffset();
  936. } else {
  937. // If the new offset would be negative, bail out.
  938. if (Offset.isPositive() && Index < Offset)
  939. return InvalidOffset();
  940. // If the new offset would be out of bounds, bail out.
  941. if (Offset.isNegative() && (Offset.isMin() || -Offset > MaxOffset))
  942. return InvalidOffset();
  943. }
  944. // Offset is valid - compute it on unsigned.
  945. int64_t WideIndex = static_cast<int64_t>(Index);
  946. int64_t WideOffset = static_cast<int64_t>(Offset);
  947. int64_t Result;
  948. if constexpr (Add)
  949. Result = WideIndex + WideOffset;
  950. else
  951. Result = WideIndex - WideOffset;
  952. S.Stk.push<Pointer>(Ptr.atIndex(static_cast<unsigned>(Result)));
  953. return true;
  954. }
  955. template <PrimType Name, class T = typename PrimConv<Name>::T>
  956. bool AddOffset(InterpState &S, CodePtr OpPC) {
  957. return OffsetHelper<T, true>(S, OpPC);
  958. }
  959. template <PrimType Name, class T = typename PrimConv<Name>::T>
  960. bool SubOffset(InterpState &S, CodePtr OpPC) {
  961. return OffsetHelper<T, false>(S, OpPC);
  962. }
  963. /// 1) Pops a Pointer from the stack.
  964. /// 2) Pops another Pointer from the stack.
  965. /// 3) Pushes the different of the indices of the two pointers on the stack.
  966. template <PrimType Name, class T = typename PrimConv<Name>::T>
  967. inline bool SubPtr(InterpState &S, CodePtr OpPC) {
  968. const Pointer &LHS = S.Stk.pop<Pointer>();
  969. const Pointer &RHS = S.Stk.pop<Pointer>();
  970. if (!Pointer::hasSameArray(LHS, RHS)) {
  971. // TODO: Diagnose.
  972. return false;
  973. }
  974. T A = T::from(LHS.getIndex());
  975. T B = T::from(RHS.getIndex());
  976. return AddSubMulHelper<T, T::sub, std::minus>(S, OpPC, A.bitWidth(), A, B);
  977. }
  978. //===----------------------------------------------------------------------===//
  979. // Destroy
  980. //===----------------------------------------------------------------------===//
  981. inline bool Destroy(InterpState &S, CodePtr OpPC, uint32_t I) {
  982. S.Current->destroy(I);
  983. return true;
  984. }
  985. //===----------------------------------------------------------------------===//
  986. // Cast, CastFP
  987. //===----------------------------------------------------------------------===//
  988. template <PrimType TIn, PrimType TOut> bool Cast(InterpState &S, CodePtr OpPC) {
  989. using T = typename PrimConv<TIn>::T;
  990. using U = typename PrimConv<TOut>::T;
  991. S.Stk.push<U>(U::from(S.Stk.pop<T>()));
  992. return true;
  993. }
  994. //===----------------------------------------------------------------------===//
  995. // Zero, Nullptr
  996. //===----------------------------------------------------------------------===//
  997. template <PrimType Name, class T = typename PrimConv<Name>::T>
  998. bool Zero(InterpState &S, CodePtr OpPC) {
  999. S.Stk.push<T>(T::zero());
  1000. return true;
  1001. }
  1002. template <PrimType Name, class T = typename PrimConv<Name>::T>
  1003. inline bool Null(InterpState &S, CodePtr OpPC) {
  1004. S.Stk.push<T>();
  1005. return true;
  1006. }
  1007. //===----------------------------------------------------------------------===//
  1008. // This, ImplicitThis
  1009. //===----------------------------------------------------------------------===//
  1010. inline bool This(InterpState &S, CodePtr OpPC) {
  1011. // Cannot read 'this' in this mode.
  1012. if (S.checkingPotentialConstantExpression()) {
  1013. return false;
  1014. }
  1015. const Pointer &This = S.Current->getThis();
  1016. if (!CheckThis(S, OpPC, This))
  1017. return false;
  1018. S.Stk.push<Pointer>(This);
  1019. return true;
  1020. }
  1021. inline bool RVOPtr(InterpState &S, CodePtr OpPC) {
  1022. assert(S.Current->getFunction()->hasRVO());
  1023. S.Stk.push<Pointer>(S.Current->getRVOPtr());
  1024. return true;
  1025. }
  1026. //===----------------------------------------------------------------------===//
  1027. // Shr, Shl
  1028. //===----------------------------------------------------------------------===//
  1029. template <PrimType NameL, PrimType NameR>
  1030. inline bool Shr(InterpState &S, CodePtr OpPC) {
  1031. using LT = typename PrimConv<NameL>::T;
  1032. using RT = typename PrimConv<NameR>::T;
  1033. const auto &RHS = S.Stk.pop<RT>();
  1034. const auto &LHS = S.Stk.pop<LT>();
  1035. const unsigned Bits = LHS.bitWidth();
  1036. if (!CheckShift<RT>(S, OpPC, RHS, Bits))
  1037. return false;
  1038. unsigned URHS = static_cast<unsigned>(RHS);
  1039. S.Stk.push<LT>(LT::from(static_cast<unsigned>(LHS) >> URHS, LHS.bitWidth()));
  1040. return true;
  1041. }
  1042. template <PrimType NameL, PrimType NameR>
  1043. inline bool Shl(InterpState &S, CodePtr OpPC) {
  1044. using LT = typename PrimConv<NameL>::T;
  1045. using RT = typename PrimConv<NameR>::T;
  1046. const auto &RHS = S.Stk.pop<RT>();
  1047. const auto &LHS = S.Stk.pop<LT>();
  1048. const unsigned Bits = LHS.bitWidth();
  1049. if (!CheckShift<RT>(S, OpPC, RHS, Bits))
  1050. return false;
  1051. unsigned URHS = static_cast<unsigned>(RHS);
  1052. S.Stk.push<LT>(LT::from(static_cast<unsigned>(LHS) << URHS, LHS.bitWidth()));
  1053. return true;
  1054. }
  1055. //===----------------------------------------------------------------------===//
  1056. // NoRet
  1057. //===----------------------------------------------------------------------===//
  1058. inline bool NoRet(InterpState &S, CodePtr OpPC) {
  1059. SourceLocation EndLoc = S.Current->getCallee()->getEndLoc();
  1060. S.FFDiag(EndLoc, diag::note_constexpr_no_return);
  1061. return false;
  1062. }
  1063. //===----------------------------------------------------------------------===//
  1064. // NarrowPtr, ExpandPtr
  1065. //===----------------------------------------------------------------------===//
  1066. inline bool NarrowPtr(InterpState &S, CodePtr OpPC) {
  1067. const Pointer &Ptr = S.Stk.pop<Pointer>();
  1068. S.Stk.push<Pointer>(Ptr.narrow());
  1069. return true;
  1070. }
  1071. inline bool ExpandPtr(InterpState &S, CodePtr OpPC) {
  1072. const Pointer &Ptr = S.Stk.pop<Pointer>();
  1073. S.Stk.push<Pointer>(Ptr.expand());
  1074. return true;
  1075. }
  1076. inline bool Call(InterpState &S, CodePtr &PC, const Function *Func) {
  1077. auto NewFrame = std::make_unique<InterpFrame>(S, Func, PC);
  1078. Pointer ThisPtr;
  1079. if (Func->hasThisPointer()) {
  1080. ThisPtr = NewFrame->getThis();
  1081. if (!CheckInvoke(S, PC, ThisPtr)) {
  1082. return false;
  1083. }
  1084. }
  1085. if (!CheckCallable(S, PC, Func))
  1086. return false;
  1087. InterpFrame *FrameBefore = S.Current;
  1088. S.Current = NewFrame.get();
  1089. APValue CallResult;
  1090. // Note that we cannot assert(CallResult.hasValue()) here since
  1091. // Ret() above only sets the APValue if the curent frame doesn't
  1092. // have a caller set.
  1093. if (Interpret(S, CallResult)) {
  1094. NewFrame.release(); // Frame was delete'd already.
  1095. assert(S.Current == FrameBefore);
  1096. // For constructors, check that all fields have been initialized.
  1097. if (Func->isConstructor() && !CheckCtorCall(S, PC, ThisPtr))
  1098. return false;
  1099. return true;
  1100. }
  1101. // Interpreting the function failed somehow. Reset to
  1102. // previous state.
  1103. S.Current = FrameBefore;
  1104. return false;
  1105. }
  1106. //===----------------------------------------------------------------------===//
  1107. // Read opcode arguments
  1108. //===----------------------------------------------------------------------===//
  1109. template <typename T> inline T ReadArg(InterpState &S, CodePtr &OpPC) {
  1110. if constexpr (std::is_pointer<T>::value) {
  1111. uint32_t ID = OpPC.read<uint32_t>();
  1112. return reinterpret_cast<T>(S.P.getNativePointer(ID));
  1113. } else {
  1114. return OpPC.read<T>();
  1115. }
  1116. }
  1117. } // namespace interp
  1118. } // namespace clang
  1119. #endif