OpLayouts.h 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. #pragma once
  6. namespace Js {
  7. ///----------------------------------------------------------------------------
  8. ///
  9. /// enum OpCode
  10. ///
  11. /// OpCode defines the set of p-code instructions available for byte-code.
  12. ///
  13. ///----------------------------------------------------------------------------
  14. enum class OpCode : ushort
  15. {
  16. #define DEF_OP(x, y, ...) x,
  17. #include "OpCodeList.h"
  18. MaxByteSizedOpcodes = 255,
  19. #include "ExtendedOpCodeList.h"
  20. ByteCodeLast,
  21. #if ENABLE_NATIVE_CODEGEN
  22. #include "BackendOpCodeList.h"
  23. #endif
  24. #undef DEF_OP
  25. Count // Number of operations
  26. };
  27. inline OpCode operator+(OpCode o1, OpCode o2) { return (OpCode)((uint)o1 + (uint)o2); }
  28. inline uint operator+(OpCode o1, uint i) { return ((uint)o1 + i); }
  29. inline uint operator+(uint i, OpCode &o2) { return (i + (uint)o2); }
  30. inline OpCode operator++(OpCode &o) { return o = (OpCode)(o + 1U); }
  31. inline OpCode operator++(OpCode &o, int) { OpCode prev_o = o; o = (OpCode)(o + 1U); return prev_o; }
  32. inline OpCode operator-(OpCode o1, OpCode o2) { return (OpCode)((uint)o1 - (uint)o2); }
  33. inline uint operator-(OpCode o1, uint i) { return ((uint)o1 - i); }
  34. inline uint operator-(uint i, OpCode &o2) { return (i - (uint)o2); }
  35. inline OpCode operator--(OpCode &o) { return o = (OpCode)(o - 1U); }
  36. inline OpCode operator--(OpCode &o, int) { return o = (OpCode)(o - 1U); }
  37. inline uint operator<<(OpCode o1, uint i) { return ((uint)o1 << i); }
  38. inline OpCode& operator+=(OpCode &o, uint i) { return (o = (OpCode)(o + i)); }
  39. inline OpCode& operator-=(OpCode &o, uint i) { return (o = (OpCode)(o - i)); }
  40. inline bool operator==(OpCode &o, uint i) { return ((uint)(o) == i); }
  41. inline bool operator==(uint i, OpCode &o) { return (i == (uint)(o)); }
  42. inline bool operator!=(OpCode &o, uint i) { return ((uint)(o) != i); }
  43. inline bool operator!=(uint i, OpCode &o) { return (i != (uint)(o)); }
  44. inline bool operator<(OpCode &o, uint i) { return ((uint)(o) < i); }
  45. inline bool operator<(uint i, OpCode &o) { return (i < (uint)(o)); }
  46. inline bool operator>(OpCode &o, uint i) { return ((uint)(o) > i); }
  47. inline bool operator>(uint i, OpCode &o) { return (i > (uint)(o)); }
  48. #if ENABLE_NATIVE_CODEGEN
  49. inline bool IsSimd128Opcode(OpCode o) { return (o > Js::OpCode::Simd128_Start && o < Js::OpCode::Simd128_End) || (o > Js::OpCode::Simd128_Start_Extend && o < Js::OpCode::Simd128_End_Extend); }
  50. inline uint Simd128OpcodeCount() { return (uint)(Js::OpCode::Simd128_End - Js::OpCode::Simd128_Start) + 1 + (uint)(Js::OpCode::Simd128_End_Extend - Js::OpCode::Simd128_Start_Extend) + 1; }
  51. inline bool IsSimd128Load(OpCode o){ return o == Js::OpCode::Simd128_LdArr_I4 || o == Js::OpCode::Simd128_LdArr_F4; }
  52. inline bool IsSimd128Store(OpCode o){ return o == Js::OpCode::Simd128_StArr_I4 || o == Js::OpCode::Simd128_StArr_F4; }
  53. inline bool IsSimd128LoadStore(OpCode o) { return IsSimd128Load(o) || IsSimd128Store(o); }
  54. #endif
  55. ///----------------------------------------------------------------------------
  56. ///
  57. /// enum OpLayoutType
  58. ///
  59. /// OpLayoutType defines a set of layouts available for OpCodes. These layouts
  60. /// correspond to "OpLayout" structs defined below, such as "OpLayoutReg1".
  61. ///
  62. ///----------------------------------------------------------------------------
  63. BEGIN_ENUM_UINT(OpLayoutType)
  64. // This define only one enum for each layout type, but not for each layout variant
  65. #define LAYOUT_TYPE(x) x,
  66. #define LAYOUT_TYPE_WMS LAYOUT_TYPE
  67. #include "LayoutTypes.h"
  68. Count,
  69. END_ENUM_UINT()
  70. ///----------------------------------------------------------------------------
  71. ///
  72. /// struct OpLayoutXYZ
  73. ///
  74. /// OpLayoutXYZ structs define the standard patterns used to layout each
  75. /// OpCode's arguments.
  76. ///
  77. /// Set up packing:
  78. /// - Since we are reading / writing from a byte-stream, and we want everything
  79. /// to be tightly aligned with no unintended spaces, change to 'byte'
  80. /// packing.
  81. /// - On processors with alignment requirements, this will automatically
  82. /// generate read / write code to handle 'unaligned' access.
  83. ///
  84. /// - 3/9/10: Changing the layouts to make all fields well-aligned. This involves
  85. /// reducing the RegSlot from 4 bytes to 2, increasing the OpCode from 1 byte to 2,
  86. /// reordering fields, and adding pads where appropriate. Note that we assume all
  87. /// layouts are preceded by a 2-byte op. The orderings and padding will need to
  88. /// be revisited for Win64.
  89. ///
  90. /// - 5/2: X86-64 alignment: Changing code to expect all opcode layout structs
  91. /// to be aligned on 4 byte boundaries (on I386 and x86-64). This aligns all
  92. /// members on their natural boundaries except for Call and Regex which require
  93. /// padding before the pointers on x86-64.
  94. ///
  95. /// - 09/12: Adding one-byte RegSlot based OpLayout. These remove all the paddings to be
  96. /// able to compress the size. Also remove paddings for non ARM build
  97. ///
  98. /// - 08/22/2011: Removed paddings for ARM & x64 as well as both support unaligned access
  99. /// There is still paddings to make sure every opcode starts at 2 byte boundary to avoid
  100. /// pathological cases.
  101. /// Note: RegSlot is changed to 4 byte instead of 1 byte in this change.
  102. ///
  103. ///----------------------------------------------------------------------------
  104. #pragma pack(push, 1)
  105. template <typename SizePolicy>
  106. struct OpLayoutT_Reg1 // R0 <- op
  107. {
  108. typename SizePolicy::RegSlotType R0;
  109. };
  110. template <typename SizePolicy>
  111. struct OpLayoutT_Reg1Unsigned1 // R0 <- op
  112. {
  113. typename SizePolicy::RegSlotType R0;
  114. typename SizePolicy::UnsignedType C1;
  115. };
  116. template <typename SizePolicy>
  117. struct OpLayoutT_Reg2 // R0 <- op R1
  118. {
  119. typename SizePolicy::RegSlotType R0;
  120. typename SizePolicy::RegSlotType R1;
  121. };
  122. template <typename SizePolicy>
  123. struct OpLayoutT_Reg2WithICIndex : public OpLayoutT_Reg2<SizePolicy>
  124. {
  125. InlineCacheIndex inlineCacheIndex;
  126. };
  127. template <typename SizePolicy>
  128. struct OpLayoutT_Reg3 // R0 <- R1 op R2 -- or -- R0 op R1 <- R2
  129. {
  130. typename SizePolicy::RegSlotType R0;
  131. typename SizePolicy::RegSlotType R1;
  132. typename SizePolicy::RegSlotType R2;
  133. };
  134. template <typename SizePolicy>
  135. struct OpLayoutT_Reg3C // R0 <- R1 op R2 with space for FastPath
  136. {
  137. typename SizePolicy::RegSlotType R0;
  138. typename SizePolicy::RegSlotType R1;
  139. typename SizePolicy::RegSlotType R2;
  140. typename SizePolicy::CacheIdType inlineCacheIndex;
  141. };
  142. template <typename SizePolicy>
  143. struct OpLayoutT_Reg2B1
  144. {
  145. typename SizePolicy::RegSlotType R0;
  146. typename SizePolicy::RegSlotType R1;
  147. byte B2;
  148. };
  149. template <typename SizePolicy>
  150. struct OpLayoutT_Reg3B1
  151. {
  152. typename SizePolicy::RegSlotType R0;
  153. typename SizePolicy::RegSlotType R1;
  154. typename SizePolicy::RegSlotType R2;
  155. byte B3;
  156. };
  157. template <typename SizePolicy>
  158. struct OpLayoutT_Reg4 // R0 <- R1 op R2 op R3
  159. {
  160. typename SizePolicy::RegSlotType R0;
  161. typename SizePolicy::RegSlotType R1;
  162. typename SizePolicy::RegSlotType R2;
  163. typename SizePolicy::RegSlotType R3;
  164. };
  165. template <typename SizePolicy>
  166. struct OpLayoutT_Reg5 // R0 <- R1 op R2 op R3 op R4
  167. {
  168. typename SizePolicy::RegSlotType R0;
  169. typename SizePolicy::RegSlotType R1;
  170. typename SizePolicy::RegSlotType R2;
  171. typename SizePolicy::RegSlotType R3;
  172. typename SizePolicy::RegSlotType R4;
  173. };
  174. template <typename SizePolicy>
  175. struct OpLayoutT_ArgNoSrc // OutArg
  176. {
  177. typename SizePolicy::ArgSlotType Arg;
  178. };
  179. template <typename SizePolicy>
  180. struct OpLayoutT_Arg // OutArg <- Reg -- or -- Reg <- InArg
  181. {
  182. typename SizePolicy::ArgSlotType Arg;
  183. typename SizePolicy::RegSlotType Reg;
  184. };
  185. struct OpLayoutBr // goto Offset
  186. {
  187. JumpOffset RelativeJumpOffset;
  188. };
  189. struct OpLayoutBrS // if (op val) goto Offset
  190. {
  191. JumpOffset RelativeJumpOffset;
  192. byte val;
  193. };
  194. template <typename SizePolicy>
  195. struct OpLayoutT_BrReg1 // if (op R1) goto Offset
  196. {
  197. JumpOffset RelativeJumpOffset;
  198. typename SizePolicy::RegSlotType R1;
  199. };
  200. template <typename SizePolicy>
  201. struct OpLayoutT_BrReg1Unsigned1
  202. {
  203. JumpOffset RelativeJumpOffset;
  204. typename SizePolicy::RegSlotType R1;
  205. typename SizePolicy::RegSlotType C2;
  206. };
  207. template <typename SizePolicy>
  208. struct OpLayoutT_BrReg2 // if (R1 op R2) goto Offset
  209. {
  210. JumpOffset RelativeJumpOffset;
  211. typename SizePolicy::RegSlotType R1;
  212. typename SizePolicy::RegSlotType R2;
  213. };
  214. struct OpLayoutBrProperty // if (R1.id) goto Offset
  215. {
  216. JumpOffset RelativeJumpOffset;
  217. RegSlot Instance;
  218. PropertyIdIndexType PropertyIdIndex;
  219. };
  220. struct OpLayoutBrLocalProperty // if (id) goto Offset
  221. {
  222. JumpOffset RelativeJumpOffset;
  223. PropertyIdIndexType PropertyIdIndex;
  224. };
  225. struct OpLayoutBrEnvProperty // if ([1].id) goto Offset
  226. {
  227. JumpOffset RelativeJumpOffset;
  228. PropertyIdIndexType PropertyIdIndex;
  229. int32 SlotIndex;
  230. };
  231. #ifdef BYTECODE_BRANCH_ISLAND
  232. struct OpLayoutBrLong
  233. {
  234. LongJumpOffset RelativeJumpOffset;
  235. };
  236. #endif
  237. struct OpLayoutStartCall
  238. {
  239. ArgSlot ArgCount;
  240. };
  241. enum CallIExtendedOptions : byte
  242. {
  243. CallIExtended_None = 0,
  244. CallIExtended_SpreadArgs = 1 << 0 // This call has arguments that need to be spread
  245. };
  246. template <typename SizePolicy>
  247. struct OpLayoutT_CallI // Return = Function(ArgCount)
  248. {
  249. typename SizePolicy::ArgSlotType ArgCount;
  250. typename SizePolicy::RegSlotSType Return;
  251. typename SizePolicy::RegSlotType Function;
  252. };
  253. template <typename SizePolicy>
  254. struct OpLayoutT_CallIExtended : public OpLayoutT_CallI<SizePolicy>
  255. {
  256. CallIExtendedOptions Options;
  257. uint32 SpreadAuxOffset; // Valid with Options & CallIExtended_SpreadArgs
  258. };
  259. template <typename SizePolicy>
  260. struct OpLayoutT_CallIFlags : public OpLayoutT_CallI<SizePolicy>
  261. {
  262. CallFlags callFlags;
  263. };
  264. template <typename SizePolicy>
  265. struct OpLayoutT_CallIWithICIndex : public OpLayoutT_CallI<SizePolicy>
  266. {
  267. InlineCacheIndex inlineCacheIndex;
  268. };
  269. template <typename SizePolicy>
  270. struct OpLayoutT_CallIFlagsWithICIndex : public OpLayoutT_CallIWithICIndex<SizePolicy>
  271. {
  272. CallFlags callFlags;
  273. };
  274. template <typename SizePolicy>
  275. struct OpLayoutT_CallIExtendedFlags : public OpLayoutT_CallIExtended<SizePolicy>
  276. {
  277. CallFlags callFlags;
  278. };
  279. template <typename SizePolicy>
  280. struct OpLayoutT_CallIExtendedWithICIndex : public OpLayoutT_CallIExtended<SizePolicy>
  281. {
  282. InlineCacheIndex inlineCacheIndex;
  283. };
  284. template <typename SizePolicy>
  285. struct OpLayoutT_CallIExtendedFlagsWithICIndex : public OpLayoutT_CallIExtendedWithICIndex<SizePolicy>
  286. {
  287. CallFlags callFlags;
  288. };
  289. template <typename SizePolicy>
  290. struct OpLayoutT_Class // class _ extends Extends { Constructor(...) { ... } }
  291. {
  292. typename SizePolicy::RegSlotType Constructor;
  293. typename SizePolicy::RegSlotSType Extends;
  294. };
  295. template <typename SizePolicy>
  296. struct OpLayoutT_ElementU // Instance.PropertyIndex = <some constant value>. e.g. undefined
  297. {
  298. typename SizePolicy::RegSlotType Instance;
  299. typename SizePolicy::PropertyIdIndexType PropertyIdIndex;
  300. };
  301. template <typename SizePolicy>
  302. struct OpLayoutT_ElementScopedU // [env].PropertyIndex = <some constant value>. e.g. undefined
  303. {
  304. typename SizePolicy::PropertyIdIndexType PropertyIdIndex;
  305. };
  306. template <typename SizePolicy>
  307. struct OpLayoutT_ElementRootU // Root.PropertyIndex = <some constant value>. e.g. undefined
  308. {
  309. typename SizePolicy::PropertyIdIndexType PropertyIdIndex;
  310. };
  311. template <typename SizePolicy>
  312. struct OpLayoutT_ElementC // Value = Instance.PropertyIndex or Instance.PropertyIndex = Value
  313. {
  314. typename SizePolicy::RegSlotType Value;
  315. typename SizePolicy::RegSlotType Instance;
  316. typename SizePolicy::PropertyIdIndexType PropertyIdIndex;
  317. };
  318. template <typename SizePolicy>
  319. struct OpLayoutT_ElementScopedC // Value = [env].PropertyIndex or [env].PropertyIndex = Value
  320. {
  321. typename SizePolicy::RegSlotType Value;
  322. typename SizePolicy::PropertyIdIndexType PropertyIdIndex;
  323. };
  324. template <typename SizePolicy>
  325. struct OpLayoutT_ElementSlot // Value = Instance[SlotIndex] or Instance[SlotIndex] = Value
  326. {
  327. int32 SlotIndex; // TODO: Make this one byte?
  328. typename SizePolicy::RegSlotType Value;
  329. typename SizePolicy::RegSlotType Instance;
  330. };
  331. template <typename SizePolicy>
  332. struct OpLayoutT_ElementSlotI1
  333. {
  334. int32 SlotIndex; // TODO: Make this one byte?
  335. typename SizePolicy::RegSlotType Value;
  336. };
  337. template <typename SizePolicy>
  338. struct OpLayoutT_ElementSlotI2
  339. {
  340. int32 SlotIndex1; // TODO: Make this one byte?
  341. int32 SlotIndex2; // TODO: Make this one byte?
  342. typename SizePolicy::RegSlotType Value;
  343. };
  344. template <typename SizePolicy>
  345. struct OpLayoutT_ElementCP // As OpLayoutElementC, with space for a FastPath LoadPatch
  346. {
  347. typename SizePolicy::RegSlotType Value;
  348. typename SizePolicy::RegSlotType Instance;
  349. typename SizePolicy::CacheIdType inlineCacheIndex;
  350. };
  351. template <typename SizePolicy>
  352. struct OpLayoutT_ElementP // As OpLayoutElementCP, but with no base pointer
  353. {
  354. typename SizePolicy::RegSlotType Value;
  355. typename SizePolicy::CacheIdType inlineCacheIndex;
  356. };
  357. template <typename SizePolicy>
  358. struct OpLayoutT_ElementPIndexed // As OpLayoutElementCP, but with scope index instead of base pointer
  359. {
  360. typename SizePolicy::RegSlotType Value;
  361. typename SizePolicy::CacheIdType inlineCacheIndex;
  362. typename SizePolicy::UnsignedType scopeIndex;
  363. };
  364. template <typename SizePolicy>
  365. struct OpLayoutT_ElementRootCP // Same as ElementCP, but for root object
  366. {
  367. RootCacheId inlineCacheIndex;
  368. typename SizePolicy::RegSlotType Value;
  369. };
  370. template <typename SizePolicy>
  371. struct OpLayoutT_ElementScopedC2 // [implied base].PropertyIndex = Value, Instance2
  372. {
  373. typename SizePolicy::RegSlotType Value;
  374. typename SizePolicy::RegSlotType Value2;
  375. typename SizePolicy::PropertyIdIndexType PropertyIdIndex;
  376. };
  377. template <typename SizePolicy>
  378. struct OpLayoutT_ElementC2 // Instance.PropertyIndex = Value, Instance2
  379. {
  380. typename SizePolicy::RegSlotType Value;
  381. typename SizePolicy::RegSlotType Instance;
  382. typename SizePolicy::RegSlotType Value2;
  383. typename SizePolicy::PropertyIdIndexType PropertyIdIndex;
  384. };
  385. template <typename SizePolicy>
  386. struct OpLayoutT_ElementI // Value = Instance[Element] or Instance[Element] = Value
  387. {
  388. typename SizePolicy::RegSlotType Value;
  389. typename SizePolicy::RegSlotType Instance;
  390. typename SizePolicy::RegSlotType Element;
  391. };
  392. template <typename SizePolicy>
  393. struct OpLayoutT_ElementUnsigned1 // Value = Instance[Element] or Instance[Element] = Value
  394. {
  395. typename SizePolicy::UnsignedType Element;
  396. typename SizePolicy::RegSlotType Value;
  397. typename SizePolicy::RegSlotType Instance;
  398. };
  399. struct OpLayoutW1
  400. {
  401. unsigned short C1;
  402. };
  403. struct OpLayoutReg1Int2 // R0 <- Var(C1, C2)
  404. {
  405. RegSlot R0;
  406. int32 C1;
  407. int32 C2;
  408. };
  409. template <typename SizePolicy>
  410. struct OpLayoutT_Reg2Int1 // R0 <- func(R1, C1)
  411. {
  412. int32 C1;
  413. typename SizePolicy::RegSlotType R0;
  414. typename SizePolicy::RegSlotType R1;
  415. };
  416. struct OpLayoutAuxNoReg
  417. {
  418. uint32 Offset;
  419. int32 C1;
  420. };
  421. struct OpLayoutAuxiliary : public OpLayoutAuxNoReg // R0 <- Load(Offset, C1)
  422. {
  423. RegSlot R0;
  424. };
  425. struct OpLayoutReg2Aux : public OpLayoutAuxiliary // R0 <- Load(Offset, R1, C1)
  426. {
  427. RegSlot R1;
  428. };
  429. template <typename SizePolicy>
  430. struct OpLayoutT_Unsigned1
  431. {
  432. typename SizePolicy::UnsignedType C1;
  433. };
  434. // Dynamic profile layout wrapper
  435. template <typename LayoutType>
  436. struct OpLayoutDynamicProfile : public LayoutType
  437. {
  438. ProfileId profileId;
  439. };
  440. template <typename LayoutType>
  441. struct OpLayoutDynamicProfile2 : public LayoutType
  442. {
  443. ProfileId profileId;
  444. ProfileId profileId2;
  445. };
  446. // Generate the multi size layout type defs
  447. #define LAYOUT_TYPE_WMS(layout) \
  448. typedef OpLayoutT_##layout<LargeLayoutSizePolicy> OpLayout##layout##_Large; \
  449. typedef OpLayoutT_##layout<MediumLayoutSizePolicy> OpLayout##layout##_Medium; \
  450. typedef OpLayoutT_##layout<SmallLayoutSizePolicy> OpLayout##layout##_Small;
  451. // Generate the profiled type defs
  452. #define LAYOUT_TYPE_PROFILED(layout) \
  453. typedef OpLayoutDynamicProfile<OpLayout##layout> OpLayoutProfiled##layout;
  454. #define LAYOUT_TYPE_PROFILED2(layout) \
  455. typedef OpLayoutDynamicProfile2<OpLayout##layout> OpLayoutProfiled2##layout;
  456. #define LAYOUT_TYPE_PROFILED_WMS(layout) \
  457. LAYOUT_TYPE_WMS(layout) \
  458. LAYOUT_TYPE_PROFILED(layout##_Large) \
  459. LAYOUT_TYPE_PROFILED(layout##_Medium) \
  460. LAYOUT_TYPE_PROFILED(layout##_Small)
  461. #define LAYOUT_TYPE_PROFILED2_WMS(layout) \
  462. LAYOUT_TYPE_PROFILED_WMS(layout) \
  463. LAYOUT_TYPE_PROFILED2(layout##_Large) \
  464. LAYOUT_TYPE_PROFILED2(layout##_Medium) \
  465. LAYOUT_TYPE_PROFILED2(layout##_Small)
  466. #include "LayoutTypes.h"
  467. #pragma pack(pop)
  468. // Generate structure to automatically map layout to its info
  469. template <OpLayoutType::_E layout> struct OpLayoutInfo;
  470. #define LAYOUT_TYPE(layout) \
  471. CompileAssert(sizeof(OpLayout##layout) <= MaxLayoutSize); \
  472. template <> struct OpLayoutInfo<OpLayoutType::layout> \
  473. { \
  474. static const bool HasMultiSizeLayout = false; \
  475. };
  476. #define LAYOUT_TYPE_WMS(layout) \
  477. CompileAssert(sizeof(OpLayout##layout##_Large) <= MaxLayoutSize); \
  478. template <> struct OpLayoutInfo<OpLayoutType::layout> \
  479. { \
  480. static const bool HasMultiSizeLayout = true; \
  481. };
  482. #include "LayoutTypes.h"
  483. // Generate structure to automatically map opcode to its info
  484. // Also generate assert to make sure the layout and opcode use the same macro with and without multiple size layout
  485. template <OpCode opcode> struct OpCodeInfo;
  486. #define DEFINE_OPCODEINFO(op, layout, extended) \
  487. CompileAssert(!OpLayoutInfo<OpLayoutType::layout>::HasMultiSizeLayout); \
  488. template <> struct OpCodeInfo<OpCode::op> \
  489. { \
  490. static const OpLayoutType::_E Layout = OpLayoutType::layout; \
  491. static const bool HasMultiSizeLayout = false; \
  492. static const bool IsExtendedOpcode = extended; \
  493. typedef OpLayout##layout LayoutType; \
  494. };
  495. #define DEFINE_OPCODEINFO_WMS(op, layout, extended) \
  496. CompileAssert(OpLayoutInfo<OpLayoutType::layout>::HasMultiSizeLayout); \
  497. template <> struct OpCodeInfo<OpCode::op> \
  498. { \
  499. static const OpLayoutType::_E Layout = OpLayoutType::layout; \
  500. static const bool HasMultiSizeLayout = true; \
  501. static const bool IsExtendedOpcode = extended; \
  502. typedef OpLayout##layout##_Large LayoutType_Large; \
  503. typedef OpLayout##layout##_Medium LayoutType_Medium; \
  504. typedef OpLayout##layout##_Small LayoutType_Small; \
  505. };
  506. #define MACRO(op, layout, ...) DEFINE_OPCODEINFO(op, layout, false)
  507. #define MACRO_WMS(op, layout, ...) DEFINE_OPCODEINFO_WMS(op, layout, false)
  508. #define MACRO_EXTEND(op, layout, ...) DEFINE_OPCODEINFO(op, layout, true)
  509. #define MACRO_EXTEND_WMS(op, layout, ...) DEFINE_OPCODEINFO_WMS(op, layout, true)
  510. #include "OpCodes.h"
  511. #undef DEFINE_OPCODEINFO
  512. #undef DEFINE_OPCODEINFO_WMS
  513. } // namespace Js