ILImporter.cs 68 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.IO;
  5. using System.Linq;
  6. using System.Text;
  7. using dnlib.DotNet;
  8. using dnlib.DotNet.Emit;
  9. namespace Natsu.Compiler
  10. {
  11. class ILImporter
  12. {
  13. private BasicBlock _headBlock;
  14. private BlockGraph _blockGraph = new BlockGraph();
  15. private readonly TextWriter _writer;
  16. private readonly int _ident;
  17. private readonly MethodDef _method;
  18. private readonly CorLibTypes _corLibTypes;
  19. private List<SpillSlot> _spillSlots = new List<SpillSlot>();
  20. private Dictionary<ExceptionHandler, ExceptionHandlerContext> _exceptions = new Dictionary<ExceptionHandler, ExceptionHandlerContext>();
  21. private int _paramIndex;
  22. private int _blockId;
  23. private int _nextSpillSlot = 0;
  24. public List<string> UserStrings { get; set; }
  25. public string ModuleName { get; set; }
  26. public ILImporter(CorLibTypes corLibTypes, MethodDef method, TextWriter writer, int ident)
  27. {
  28. _corLibTypes = corLibTypes;
  29. _method = method;
  30. _writer = writer;
  31. _ident = ident;
  32. }
  33. public void ImportNormalBlocks()
  34. {
  35. _headBlock = ImportBlocks(_method.Body.Instructions, _method.Body.Instructions.FirstOrDefault());
  36. }
  37. public void ImportExceptionBlocks()
  38. {
  39. foreach (var handler in _method.Body.ExceptionHandlers)
  40. {
  41. var ctx = new ExceptionHandlerContext
  42. {
  43. Handler = handler,
  44. HeadBlock = ImportBlocks(_method.Body.Instructions, handler.HandlerStart)
  45. };
  46. _exceptions.Add(handler, ctx);
  47. }
  48. }
  49. Instruction PrevInst(Instruction inst)
  50. {
  51. var instructions = _method.Body.Instructions;
  52. var index = instructions.IndexOf(inst);
  53. if (index == 0)
  54. return null;
  55. return instructions[index - 1];
  56. }
  57. private BasicBlock ImportBlocks(IList<Instruction> instructions, Instruction firstInst)
  58. {
  59. Instruction NextInst(Instruction inst)
  60. {
  61. var index = instructions.IndexOf(inst);
  62. if (index < instructions.Count - 1)
  63. return instructions[index + 1];
  64. return null;
  65. }
  66. BasicBlock ImportBlock(BasicBlock parent, Instruction inst)
  67. {
  68. if (inst == null) return null;
  69. var block = new BasicBlock { Id = _blockId++, Parent = parent };
  70. _blockGraph.Blocks.Add(inst, block);
  71. bool conti = true;
  72. void AddNext(Instruction next)
  73. {
  74. if (!_blockGraph.Blocks.TryGetValue(next, out var nextBlock))
  75. nextBlock = ImportBlock(block, next);
  76. if (nextBlock != null)
  77. block.Next.Add(nextBlock);
  78. }
  79. while (conti)
  80. {
  81. switch (inst.OpCode.Code)
  82. {
  83. case Code.Br:
  84. case Code.Br_S:
  85. block.Instructions.Add(inst);
  86. AddNext((Instruction)inst.Operand);
  87. conti = false;
  88. break;
  89. case Code.Leave:
  90. case Code.Leave_S:
  91. block.Instructions.Add(inst);
  92. AddNext((Instruction)inst.Operand);
  93. conti = false;
  94. break;
  95. case Code.Brfalse:
  96. case Code.Brfalse_S:
  97. case Code.Brtrue:
  98. case Code.Brtrue_S:
  99. case Code.Blt_S:
  100. case Code.Blt:
  101. case Code.Blt_Un_S:
  102. case Code.Blt_Un:
  103. case Code.Ble_S:
  104. case Code.Ble:
  105. case Code.Ble_Un:
  106. case Code.Ble_Un_S:
  107. case Code.Beq_S:
  108. case Code.Beq:
  109. case Code.Bge_S:
  110. case Code.Bge:
  111. case Code.Bge_Un_S:
  112. case Code.Bge_Un:
  113. case Code.Bgt_S:
  114. case Code.Bgt:
  115. case Code.Bgt_Un_S:
  116. case Code.Bgt_Un:
  117. case Code.Bne_Un_S:
  118. case Code.Bne_Un:
  119. block.Instructions.Add(inst);
  120. AddNext((Instruction)inst.Operand);
  121. AddNext(NextInst(inst));
  122. conti = false;
  123. break;
  124. case Code.Ret:
  125. case Code.Throw:
  126. case Code.Endfinally:
  127. case Code.Endfilter:
  128. block.Instructions.Add(inst);
  129. conti = false;
  130. break;
  131. case Code.Switch:
  132. block.Instructions.Add(inst);
  133. foreach (var c in (IEnumerable<Instruction>)inst.Operand)
  134. AddNext(c);
  135. AddNext(NextInst(inst));
  136. conti = false;
  137. break;
  138. default:
  139. if (inst.OpCode.Code != Code.Box && inst.OpCode.Code.ToString().StartsWith('B'))
  140. throw new NotImplementedException();
  141. block.Instructions.Add(inst);
  142. inst = NextInst(inst);
  143. break;
  144. }
  145. }
  146. return block;
  147. }
  148. if (firstInst != null)
  149. return ImportBlock(null, firstInst);
  150. else
  151. return new BasicBlock { Id = 0 };
  152. }
  153. internal void Gencode()
  154. {
  155. var visited = new HashSet<BasicBlock>();
  156. VisitBlock(_ident, _headBlock, visited);
  157. var spillsName = new HashSet<string>();
  158. // spills
  159. foreach (var spill in _spillSlots.Distinct())
  160. {
  161. if (spillsName.Add(spill.Name))
  162. _writer.Ident(_ident).WriteLine($"{TypeUtils.EscapeStackTypeName(spill.Entry.Type)} {spill.Name};");
  163. }
  164. visited.Clear();
  165. VisitBlockText(_headBlock, _writer, visited);
  166. }
  167. private void VisitBlockText(BasicBlock block, TextWriter writer, HashSet<BasicBlock> visited)
  168. {
  169. var blocks = new List<BasicBlock>();
  170. void AddBlock(BasicBlock headBlock)
  171. {
  172. visited.Add(headBlock);
  173. blocks.Add(headBlock);
  174. foreach (var next in headBlock.Next)
  175. {
  176. if (!visited.Contains(next))
  177. AddBlock(next);
  178. }
  179. }
  180. AddBlock(block);
  181. foreach (var cntBlock in blocks.Where(x => x.Instructions.Any())
  182. .OrderBy(x => x.Instructions[0].Offset))
  183. {
  184. writer.Write(cntBlock.Text);
  185. }
  186. }
  187. private void VisitBlock(int ident, BasicBlock block, HashSet<BasicBlock> visited, StringWriter writer = null, EvaluationStack stack = null)
  188. {
  189. visited.Add(block);
  190. writer = writer ?? new StringWriter();
  191. stack = stack ?? new EvaluationStack(writer, ident, _paramIndex);
  192. writer.WriteLine(ILUtils.GetLabel(_method, block.Id) + ":");
  193. // import spills
  194. if (block.Parent != null)
  195. {
  196. foreach (var spill in Enumerable.Reverse(block.Parent.Spills))
  197. stack.Push(spill.Entry.Type, spill.Name);
  198. }
  199. var instLines = new List<string>();
  200. foreach (var op in block.Instructions)
  201. {
  202. var instW = new StringWriter();
  203. stack.SetWriter(instW);
  204. var tryEnter = (from e in _exceptions
  205. where !e.Value.EnterProcessed && e.Key.TryStart == op
  206. select e).FirstOrDefault();
  207. if (tryEnter.Key != null)
  208. {
  209. EvaluationStack tryEnterStack = null;
  210. if (tryEnter.Key.HandlerType == ExceptionHandlerType.Finally)
  211. {
  212. if (_method.FullName.Contains("Concat"))
  213. ;
  214. instW.Ident(ident).WriteLine("{");
  215. ident += 1;
  216. stack.Ident = ident;
  217. instW.Ident(ident).WriteLine("auto _scope_finally = natsu::make_finally([&]{");
  218. VisitBlock(ident + 1, tryEnter.Value.HeadBlock, new HashSet<BasicBlock>(), stack: tryEnterStack);
  219. VisitBlockText(tryEnter.Value.HeadBlock, instW, visited);
  220. instW.Ident(ident).WriteLine("});");
  221. tryEnter.Value.EnterProcessed = true;
  222. }
  223. else if (tryEnter.Key.HandlerType == ExceptionHandlerType.Catch)
  224. {
  225. }
  226. }
  227. WriteInstruction(instW, op, stack, ident, block);
  228. var tryExit = (from e in _exceptions
  229. where !e.Value.ExitProcessed && PrevInst(e.Key.TryEnd) == op
  230. select e).FirstOrDefault();
  231. if (tryExit.Key != null)
  232. {
  233. if (tryExit.Key.HandlerType == ExceptionHandlerType.Finally)
  234. {
  235. ident -= 1;
  236. stack.Ident = ident;
  237. instW.Ident(ident).WriteLine("}");
  238. tryExit.Value.ExitProcessed = true;
  239. }
  240. else if (tryExit.Key.HandlerType == ExceptionHandlerType.Catch)
  241. {
  242. }
  243. }
  244. instLines.Add(instW.ToString());
  245. }
  246. foreach (var instLine in instLines.Take(instLines.Count - 1))
  247. writer.Write(instLine);
  248. int slotIndex = 0;
  249. // export spills
  250. while (block.Next.Count != 0 && !stack.Empty)
  251. {
  252. var spill = AddSpillSlot(slotIndex++, stack.Pop(), block);
  253. writer.Ident(ident).WriteLine($"{spill.Name} = {spill.Entry.Expression};");
  254. block.Spills.Add(spill);
  255. }
  256. writer.Write(instLines.Last());
  257. block.Text = writer.ToString();
  258. _paramIndex = stack.ParamIndex;
  259. foreach (var next in block.Next)
  260. {
  261. if (!visited.Contains(next))
  262. VisitBlock(ident, next, visited);
  263. }
  264. }
  265. private SpillSlot AddSpillSlot(int index, StackEntry stackEntry, BasicBlock block)
  266. {
  267. if (block.Next != null)
  268. {
  269. foreach (var slot in _spillSlots)
  270. {
  271. if (slot.Next != block.Next && slot.Index == index)
  272. {
  273. foreach (var next in slot.Next)
  274. {
  275. if (block.Next.Contains(next))
  276. {
  277. var newSlot = new SpillSlot { Index = slot.Index, Name = slot.Name, Entry = stackEntry, Next = block.Next };
  278. _spillSlots.Add(newSlot);
  279. return newSlot;
  280. }
  281. }
  282. }
  283. }
  284. }
  285. {
  286. var slot = new SpillSlot { Index = index, Name = "_s" + _nextSpillSlot++.ToString(), Entry = stackEntry, Next = block.Next };
  287. _spillSlots.Add(slot);
  288. return slot;
  289. }
  290. }
  291. private void WriteInstruction(TextWriter writer, Instruction op, EvaluationStack stack, int ident, BasicBlock block)
  292. {
  293. var emitter = new OpEmitter { CorLibTypes = _corLibTypes, ModuleName = ModuleName, UserStrings = UserStrings, Method = _method, Op = op, Stack = stack, Ident = ident, Block = block, Writer = writer };
  294. bool isSpecial = true;
  295. if (op.IsLdarg())
  296. emitter.Ldarg();
  297. else if (op.IsStarg())
  298. emitter.Starg();
  299. else if (op.IsLdcI4())
  300. emitter.LdcI4();
  301. else if (op.IsLdloc())
  302. emitter.Ldloc();
  303. else if (op.IsStloc())
  304. emitter.Stloc();
  305. else if (op.IsBr())
  306. emitter.Br();
  307. else if (op.IsLeave())
  308. emitter.Leave();
  309. else if (op.IsBrtrue())
  310. emitter.Brtrue();
  311. else if (op.IsBrfalse())
  312. emitter.Brfalse();
  313. else
  314. isSpecial = false;
  315. if (!isSpecial)
  316. {
  317. switch (op.OpCode.Code)
  318. {
  319. case Code.Call:
  320. emitter.Call();
  321. break;
  322. case Code.Callvirt:
  323. emitter.Callvirt();
  324. break;
  325. case Code.Nop:
  326. emitter.Nop();
  327. break;
  328. case Code.Ret:
  329. emitter.Ret();
  330. break;
  331. case Code.Endfinally:
  332. emitter.Endfinally();
  333. break;
  334. case Code.Throw:
  335. emitter.Throw();
  336. break;
  337. case Code.Neg:
  338. emitter.Neg();
  339. break;
  340. case Code.Not:
  341. emitter.Not();
  342. break;
  343. case Code.Add:
  344. emitter.Add();
  345. break;
  346. case Code.Sub:
  347. emitter.Sub();
  348. break;
  349. case Code.Mul:
  350. emitter.Mul();
  351. break;
  352. case Code.Div:
  353. emitter.Div();
  354. break;
  355. case Code.Div_Un:
  356. emitter.Div_Un();
  357. break;
  358. case Code.Rem:
  359. emitter.Rem();
  360. break;
  361. case Code.Rem_Un:
  362. emitter.Rem_Un();
  363. break;
  364. case Code.And:
  365. emitter.And();
  366. break;
  367. case Code.Or:
  368. emitter.Or();
  369. break;
  370. case Code.Xor:
  371. emitter.Xor();
  372. break;
  373. case Code.Shl:
  374. emitter.Shl();
  375. break;
  376. case Code.Shr:
  377. emitter.Shr();
  378. break;
  379. case Code.Shr_Un:
  380. emitter.Shr_Un();
  381. break;
  382. case Code.Clt:
  383. emitter.Clt();
  384. break;
  385. case Code.Clt_Un:
  386. emitter.Clt_Un();
  387. break;
  388. case Code.Ceq:
  389. emitter.Ceq();
  390. break;
  391. case Code.Cgt:
  392. emitter.Cgt();
  393. break;
  394. case Code.Cgt_Un:
  395. emitter.Cgt_Un();
  396. break;
  397. case Code.Ldc_I8:
  398. emitter.Ldc_I8();
  399. break;
  400. case Code.Ldc_R4:
  401. emitter.Ldc_R4();
  402. break;
  403. case Code.Ldc_R8:
  404. emitter.Ldc_R8();
  405. break;
  406. case Code.Ldstr:
  407. emitter.Ldstr();
  408. break;
  409. case Code.Ldsfld:
  410. emitter.Ldsfld();
  411. break;
  412. case Code.Ldfld:
  413. emitter.Ldfld();
  414. break;
  415. case Code.Stsfld:
  416. emitter.Stsfld();
  417. break;
  418. case Code.Stfld:
  419. emitter.Stfld();
  420. break;
  421. case Code.Ldarga_S:
  422. case Code.Ldarga:
  423. emitter.Ldarga();
  424. break;
  425. case Code.Ldloca_S:
  426. case Code.Ldloca:
  427. emitter.Ldloca();
  428. break;
  429. case Code.Ldflda:
  430. emitter.Ldflda();
  431. break;
  432. case Code.Ldsflda:
  433. emitter.Ldsflda();
  434. break;
  435. case Code.Ldind_I1:
  436. emitter.Ldind_I1();
  437. break;
  438. case Code.Ldind_I2:
  439. emitter.Ldind_I2();
  440. break;
  441. case Code.Ldind_I4:
  442. emitter.Ldind_I4();
  443. break;
  444. case Code.Ldind_I8:
  445. emitter.Ldind_I8();
  446. break;
  447. case Code.Ldind_R4:
  448. emitter.Ldind_R4();
  449. break;
  450. case Code.Ldind_R8:
  451. emitter.Ldind_R8();
  452. break;
  453. case Code.Ldind_I:
  454. emitter.Ldind_I();
  455. break;
  456. case Code.Ldind_Ref:
  457. emitter.Ldind_Ref();
  458. break;
  459. case Code.Ldind_U1:
  460. emitter.Ldind_U1();
  461. break;
  462. case Code.Ldind_U2:
  463. emitter.Ldind_U2();
  464. break;
  465. case Code.Ldind_U4:
  466. emitter.Ldind_U4();
  467. break;
  468. case Code.Stind_I1:
  469. emitter.Stind_I1();
  470. break;
  471. case Code.Stind_I2:
  472. emitter.Stind_I2();
  473. break;
  474. case Code.Stind_I4:
  475. emitter.Stind_I4();
  476. break;
  477. case Code.Stind_I8:
  478. emitter.Stind_I8();
  479. break;
  480. case Code.Stind_I:
  481. emitter.Stind_I();
  482. break;
  483. case Code.Stind_R4:
  484. emitter.Stind_R4();
  485. break;
  486. case Code.Stind_R8:
  487. emitter.Stind_R8();
  488. break;
  489. case Code.Stind_Ref:
  490. emitter.Stind_Ref();
  491. break;
  492. case Code.Ldelem_I1:
  493. emitter.Ldelem_I1();
  494. break;
  495. case Code.Ldelem_I2:
  496. emitter.Ldelem_I2();
  497. break;
  498. case Code.Ldelem_I4:
  499. emitter.Ldelem_I4();
  500. break;
  501. case Code.Ldelem_I8:
  502. emitter.Ldelem_I8();
  503. break;
  504. case Code.Ldelem_R4:
  505. emitter.Ldelem_R4();
  506. break;
  507. case Code.Ldelem_R8:
  508. emitter.Ldelem_R8();
  509. break;
  510. case Code.Ldelem_I:
  511. emitter.Ldelem_I();
  512. break;
  513. case Code.Ldelem_Ref:
  514. emitter.Ldelem_Ref();
  515. break;
  516. case Code.Ldelem_U1:
  517. emitter.Ldelem_U1();
  518. break;
  519. case Code.Ldelem_U2:
  520. emitter.Ldelem_U2();
  521. break;
  522. case Code.Ldelem_U4:
  523. emitter.Ldelem_U4();
  524. break;
  525. case Code.Ldelem:
  526. emitter.Ldelem();
  527. break;
  528. case Code.Stelem_I1:
  529. emitter.Stelem_I1();
  530. break;
  531. case Code.Stelem_I2:
  532. emitter.Stelem_I2();
  533. break;
  534. case Code.Stelem_I4:
  535. emitter.Stelem_I4();
  536. break;
  537. case Code.Stelem_I8:
  538. emitter.Stelem_I8();
  539. break;
  540. case Code.Stelem_R4:
  541. emitter.Stelem_R4();
  542. break;
  543. case Code.Stelem_R8:
  544. emitter.Stelem_R8();
  545. break;
  546. case Code.Stelem_Ref:
  547. emitter.Stelem_Ref();
  548. break;
  549. case Code.Stelem:
  550. emitter.Stelem();
  551. break;
  552. case Code.Ldelema:
  553. emitter.Ldelema();
  554. break;
  555. case Code.Ldnull:
  556. emitter.Ldnull();
  557. break;
  558. case Code.Newarr:
  559. emitter.Newarr();
  560. break;
  561. case Code.Initobj:
  562. emitter.Initobj();
  563. break;
  564. case Code.Box:
  565. emitter.Box();
  566. break;
  567. case Code.Newobj:
  568. emitter.Newobj();
  569. break;
  570. case Code.Ldobj:
  571. emitter.Ldobj();
  572. break;
  573. case Code.Stobj:
  574. emitter.Stobj();
  575. break;
  576. case Code.Ldtoken:
  577. emitter.Ldtoken();
  578. break;
  579. case Code.Isinst:
  580. emitter.Isinst();
  581. break;
  582. case Code.Unbox_Any:
  583. emitter.Unbox_Any();
  584. break;
  585. case Code.Unbox:
  586. emitter.Unbox();
  587. break;
  588. case Code.Castclass:
  589. emitter.Castclass();
  590. break;
  591. case Code.Ldlen:
  592. emitter.Ldlen();
  593. break;
  594. case Code.Localloc:
  595. emitter.Localloc();
  596. break;
  597. case Code.Conv_I1:
  598. emitter.Conv_I1();
  599. break;
  600. case Code.Conv_I2:
  601. emitter.Conv_I2();
  602. break;
  603. case Code.Conv_I4:
  604. emitter.Conv_I4();
  605. break;
  606. case Code.Conv_I8:
  607. emitter.Conv_I8();
  608. break;
  609. case Code.Conv_I:
  610. emitter.Conv_I();
  611. break;
  612. case Code.Conv_R4:
  613. emitter.Conv_R4();
  614. break;
  615. case Code.Conv_R8:
  616. emitter.Conv_R8();
  617. break;
  618. case Code.Conv_U1:
  619. emitter.Conv_U1();
  620. break;
  621. case Code.Conv_U2:
  622. emitter.Conv_U2();
  623. break;
  624. case Code.Conv_U4:
  625. emitter.Conv_U4();
  626. break;
  627. case Code.Conv_U8:
  628. emitter.Conv_U8();
  629. break;
  630. case Code.Conv_U:
  631. emitter.Conv_U();
  632. break;
  633. case Code.Conv_Ovf_I1:
  634. emitter.Conv_Ovf_I1();
  635. break;
  636. case Code.Conv_Ovf_I2:
  637. emitter.Conv_Ovf_I2();
  638. break;
  639. case Code.Conv_Ovf_I4:
  640. emitter.Conv_Ovf_I4();
  641. break;
  642. case Code.Conv_Ovf_I8:
  643. emitter.Conv_Ovf_I8();
  644. break;
  645. case Code.Conv_Ovf_I:
  646. emitter.Conv_Ovf_I();
  647. break;
  648. case Code.Conv_Ovf_U1:
  649. emitter.Conv_Ovf_U1();
  650. break;
  651. case Code.Conv_Ovf_U2:
  652. emitter.Conv_Ovf_U2();
  653. break;
  654. case Code.Conv_Ovf_U4:
  655. emitter.Conv_Ovf_U4();
  656. break;
  657. case Code.Conv_Ovf_U8:
  658. emitter.Conv_Ovf_U8();
  659. break;
  660. case Code.Conv_Ovf_U:
  661. emitter.Conv_Ovf_U();
  662. break;
  663. case Code.Conv_Ovf_I1_Un:
  664. emitter.Conv_Ovf_I1_Un();
  665. break;
  666. case Code.Conv_Ovf_I2_Un:
  667. emitter.Conv_Ovf_I2_Un();
  668. break;
  669. case Code.Conv_Ovf_I4_Un:
  670. emitter.Conv_Ovf_I4_Un();
  671. break;
  672. case Code.Conv_Ovf_I8_Un:
  673. emitter.Conv_Ovf_I8_Un();
  674. break;
  675. case Code.Conv_Ovf_I_Un:
  676. emitter.Conv_Ovf_I_Un();
  677. break;
  678. case Code.Conv_Ovf_U1_Un:
  679. emitter.Conv_Ovf_U1_Un();
  680. break;
  681. case Code.Conv_Ovf_U2_Un:
  682. emitter.Conv_Ovf_U2_Un();
  683. break;
  684. case Code.Conv_Ovf_U4_Un:
  685. emitter.Conv_Ovf_U4_Un();
  686. break;
  687. case Code.Conv_Ovf_U8_Un:
  688. emitter.Conv_Ovf_U8_Un();
  689. break;
  690. case Code.Conv_Ovf_U_Un:
  691. emitter.Conv_Ovf_U_Un();
  692. break;
  693. case Code.Blt_S:
  694. case Code.Blt:
  695. emitter.Blt();
  696. break;
  697. case Code.Blt_Un_S:
  698. case Code.Blt_Un:
  699. emitter.Blt_Un();
  700. break;
  701. case Code.Ble_S:
  702. case Code.Ble:
  703. emitter.Ble();
  704. break;
  705. case Code.Ble_Un_S:
  706. case Code.Ble_Un:
  707. emitter.Ble_Un();
  708. break;
  709. case Code.Beq_S:
  710. case Code.Beq:
  711. emitter.Beq();
  712. break;
  713. case Code.Bge_S:
  714. case Code.Bge:
  715. emitter.Bge();
  716. break;
  717. case Code.Bge_Un_S:
  718. case Code.Bge_Un:
  719. emitter.Bge_Un();
  720. break;
  721. case Code.Bgt_S:
  722. case Code.Bgt:
  723. emitter.Bgt();
  724. break;
  725. case Code.Bgt_Un_S:
  726. case Code.Bgt_Un:
  727. emitter.Bgt_Un();
  728. break;
  729. case Code.Bne_Un_S:
  730. case Code.Bne_Un:
  731. emitter.Bne_Un();
  732. break;
  733. case Code.Switch:
  734. emitter.Switch();
  735. break;
  736. case Code.Dup:
  737. emitter.Dup();
  738. break;
  739. case Code.Ldftn:
  740. emitter.Ldftn();
  741. break;
  742. case Code.Ldvirtftn:
  743. emitter.Ldvirtftn();
  744. break;
  745. case Code.Pop:
  746. emitter.Pop();
  747. break;
  748. case Code.Sizeof:
  749. emitter.Sizeof();
  750. break;
  751. case Code.Constrained:
  752. stack.Constrained = (ITypeDefOrRef)op.Operand;
  753. break;
  754. case Code.Volatile:
  755. stack.Volatile = true;
  756. break;
  757. case Code.Readonly:
  758. break;
  759. default:
  760. throw new NotSupportedException(op.OpCode.Code.ToString());
  761. }
  762. }
  763. }
  764. private class ExceptionHandlerContext
  765. {
  766. public ExceptionHandler Handler;
  767. public bool EnterProcessed;
  768. public bool ExitProcessed;
  769. public BasicBlock HeadBlock;
  770. }
  771. }
  772. class OpEmitter
  773. {
  774. public Instruction Op { get; set; }
  775. public EvaluationStack Stack { get; set; }
  776. public int Ident { get; set; }
  777. public BasicBlock Block { get; set; }
  778. public MethodDef Method { get; set; }
  779. public TextWriter Writer { get; set; }
  780. public string ModuleName { get; set; }
  781. public List<string> UserStrings { get; set; }
  782. public CorLibTypes CorLibTypes { get; set; }
  783. // Unary
  784. public void Neg() => Unary("-");
  785. public void Not() => Unary("~");
  786. // Binary
  787. public void Add() => Binary("+");
  788. public void Sub() => Binary("-");
  789. public void Mul() => Binary("*");
  790. public void Div() => Binary("/");
  791. public void Div_Un() => Binary_Un("/");
  792. public void Rem() => Binary("%");
  793. public void Rem_Un() => Binary_Un("%");
  794. public void And() => Binary("&");
  795. public void Or() => Binary("|");
  796. public void Xor() => Binary("^");
  797. public void Shl() => Binary("<<");
  798. public void Shr() => Binary(">>");
  799. public void Shr_Un() => Binary_Un(">>");
  800. public void Clt() => Compare("<");
  801. public void Clt_Un() => Compare_Un("<");
  802. public void Ceq() => Compare("==");
  803. public void Cgt() => Compare(">");
  804. public void Cgt_Un() => Compare_Un(">");
  805. // Branch
  806. public void Brtrue() => BranchIf(string.Empty);
  807. public void Brfalse() => BranchIf("!");
  808. public void Blt() => BranchCompare("<");
  809. public void Blt_Un() => BranchCompare_Un("<");
  810. public void Ble() => BranchCompare("<=");
  811. public void Ble_Un() => BranchCompare_Un("<=");
  812. public void Beq() => BranchCompare("==");
  813. public void Bge() => BranchCompare(">=");
  814. public void Bge_Un() => BranchCompare_Un(">=");
  815. public void Bgt() => BranchCompare(">");
  816. public void Bgt_Un() => BranchCompare_Un(">");
  817. public void Bne() => BranchCompare("!=");
  818. public void Bne_Un() => BranchCompare_Un("!=");
  819. // Conversion
  820. public void Conv_I1() => Conversion(CorLibTypes.SByte, "i1");
  821. public void Conv_I2() => Conversion(CorLibTypes.Int16, "i2");
  822. public void Conv_I4() => Conversion(CorLibTypes.Int32, "i4");
  823. public void Conv_I8() => Conversion(CorLibTypes.Int64, "i8");
  824. public void Conv_I() => Conversion(CorLibTypes.IntPtr, "i");
  825. public void Conv_R4() => Conversion(CorLibTypes.Single, "r4");
  826. public void Conv_R8() => Conversion(CorLibTypes.Double, "r8");
  827. public void Conv_U1() => Conversion(CorLibTypes.Byte, "u1");
  828. public void Conv_U2() => Conversion(CorLibTypes.UInt16, "u2");
  829. public void Conv_U4() => Conversion(CorLibTypes.UInt32, "u4");
  830. public void Conv_U8() => Conversion(CorLibTypes.UInt64, "u8");
  831. public void Conv_U() => Conversion(CorLibTypes.UIntPtr, "u");
  832. public void Conv_Ovf_I1() => Conversion(CorLibTypes.SByte, "ovf_i1");
  833. public void Conv_Ovf_I2() => Conversion(CorLibTypes.Int16, "ovf_i2");
  834. public void Conv_Ovf_I4() => Conversion(CorLibTypes.Int32, "ovf_i4");
  835. public void Conv_Ovf_I8() => Conversion(CorLibTypes.Int64, "ovf_i8");
  836. public void Conv_Ovf_I() => Conversion(CorLibTypes.IntPtr, "ovf_i");
  837. public void Conv_Ovf_U1() => Conversion(CorLibTypes.Byte, "ovf_u1");
  838. public void Conv_Ovf_U2() => Conversion(CorLibTypes.UInt16, "ovf_u2");
  839. public void Conv_Ovf_U4() => Conversion(CorLibTypes.UInt32, "ovf_u4");
  840. public void Conv_Ovf_U8() => Conversion(CorLibTypes.UInt64, "ovf_u8");
  841. public void Conv_Ovf_U() => Conversion(CorLibTypes.UIntPtr, "ovf_u");
  842. public void Conv_Ovf_I1_Un() => Conversion(CorLibTypes.SByte, "ovf_i1_un");
  843. public void Conv_Ovf_I2_Un() => Conversion(CorLibTypes.Int16, "ovf_i2_un");
  844. public void Conv_Ovf_I4_Un() => Conversion(CorLibTypes.Int32, "ovf_i4_un");
  845. public void Conv_Ovf_I8_Un() => Conversion(CorLibTypes.Int64, "ovf_i8_un");
  846. public void Conv_Ovf_I_Un() => Conversion(CorLibTypes.IntPtr, "ovf_i_un");
  847. public void Conv_Ovf_U1_Un() => Conversion(CorLibTypes.Byte, "ovf_u1_un");
  848. public void Conv_Ovf_U2_Un() => Conversion(CorLibTypes.UInt16, "ovf_u2_un");
  849. public void Conv_Ovf_U4_Un() => Conversion(CorLibTypes.UInt32, "ovf_u4_un");
  850. public void Conv_Ovf_U8_Un() => Conversion(CorLibTypes.UInt64, "ovf_u8_un");
  851. public void Conv_Ovf_U_Un() => Conversion(CorLibTypes.UIntPtr, "ovf_u_un");
  852. // Ldind
  853. public void Ldind_I1() => Ldind(CorLibTypes.SByte);
  854. public void Ldind_I2() => Ldind(CorLibTypes.Int16);
  855. public void Ldind_I4() => Ldind(CorLibTypes.Int32);
  856. public void Ldind_I8() => Ldind(CorLibTypes.Int64);
  857. public void Ldind_R4() => Ldind(CorLibTypes.Single);
  858. public void Ldind_R8() => Ldind(CorLibTypes.Double);
  859. public void Ldind_I() => Ldind(CorLibTypes.IntPtr);
  860. public void Ldind_Ref()
  861. {
  862. var addr = Stack.Pop();
  863. Stack.Push(addr.Type.TypeSig.Next, $"(*{addr.Expression})");
  864. }
  865. public void Ldind_U1() => Ldind(CorLibTypes.Byte);
  866. public void Ldind_U2() => Ldind(CorLibTypes.UInt16);
  867. public void Ldind_U4() => Ldind(CorLibTypes.UInt32);
  868. // Stind
  869. public void Stind_I1() => Stind("i1");
  870. public void Stind_I2() => Stind("i2");
  871. public void Stind_I4() => Stind("i4");
  872. public void Stind_I8() => Stind("i8");
  873. public void Stind_R4() => Stind("r4");
  874. public void Stind_R8() => Stind("r8");
  875. public void Stind_I() => Stind("i");
  876. public void Stind_Ref() => Stind("ref");
  877. // Ldelem
  878. public void Ldelem_I1() => Ldelem(CorLibTypes.SByte, "i1");
  879. public void Ldelem_I2() => Ldelem(CorLibTypes.Int16, "i2");
  880. public void Ldelem_I4() => Ldelem(CorLibTypes.Int32, "i4");
  881. public void Ldelem_I8() => Ldelem(CorLibTypes.Int64, "i8");
  882. public void Ldelem_R4() => Ldelem(CorLibTypes.Single, "r4");
  883. public void Ldelem_R8() => Ldelem(CorLibTypes.Double, "r8");
  884. public void Ldelem_I() => Ldelem(CorLibTypes.IntPtr, "i");
  885. public void Ldelem_Ref()
  886. {
  887. var index = Stack.Pop();
  888. var array = Stack.Pop();
  889. var elemType = array.Type.TypeSig.Next;
  890. Stack.Push(elemType.ToTypeDefOrRef(), $"{array.Expression}->at({index.Expression})");
  891. }
  892. public void Ldelem_U1() => Ldelem(CorLibTypes.Byte, "u1");
  893. public void Ldelem_U2() => Ldelem(CorLibTypes.UInt16, "u2");
  894. public void Ldelem_U4() => Ldelem(CorLibTypes.UInt32, "u4");
  895. // Stelem
  896. public void Stelem_I1() => Stelem("i1");
  897. public void Stelem_I2() => Stelem("i2");
  898. public void Stelem_I4() => Stelem("i4");
  899. public void Stelem_I8() => Stelem("i8");
  900. public void Stelem_R4() => Stelem("r4");
  901. public void Stelem_R8() => Stelem("r8");
  902. public void Stelem_I() => Stelem("i");
  903. public void Stelem_Ref() => Stelem("ref");
  904. public void Ldarg()
  905. {
  906. var param = Op.GetParameter(Method.Parameters.ToList());
  907. var paramName = param.IsHiddenThisParameter ? "_this" : param.ToString();
  908. Stack.Push(TypeUtils.GetStackType(param.Type), $"{paramName}", computed: false);
  909. }
  910. public void Starg()
  911. {
  912. var param = Op.GetParameter(Method.Parameters.ToList());
  913. var paramName = param.IsHiddenThisParameter ? "_this" : param.ToString();
  914. var value = Stack.Pop();
  915. Writer.Ident(Ident).WriteLine($"{paramName} = {CastExpression(param.Type, value)};");
  916. }
  917. public void Ldarga()
  918. {
  919. var param = Op.GetParameter(Method.Parameters.ToList());
  920. var paramName = param.IsHiddenThisParameter ? "_this" : param.ToString();
  921. Stack.Push(TypeUtils.GetStackType(new ByRefSig(param.Type)), $"::natsu::ops::ref({paramName})", computed: true);
  922. }
  923. public void LdcI4()
  924. {
  925. var value = Op.GetLdcI4Value();
  926. Stack.Push(CorLibTypes.Int32, $"{TypeUtils.LiteralConstant(value)}", computed: true);
  927. }
  928. public void Ldc_I8()
  929. {
  930. var value = (long)Op.Operand;
  931. Stack.Push(CorLibTypes.Int64, $"{TypeUtils.LiteralConstant(value)}", computed: true);
  932. }
  933. public void Ldc_R4()
  934. {
  935. var value = (float)Op.Operand;
  936. Stack.Push(CorLibTypes.Single, $"{TypeUtils.LiteralConstant(value)}", computed: true);
  937. }
  938. public void Ldc_R8()
  939. {
  940. var value = (double)Op.Operand;
  941. Stack.Push(CorLibTypes.Double, $"{TypeUtils.LiteralConstant(value)}", computed: true);
  942. }
  943. public void Call()
  944. {
  945. var member = (IMethod)Op.Operand;
  946. var method = member.MethodSig;
  947. var para = new List<(TypeSig destType, StackEntry src)>();
  948. var parasCount = method.Params.Count;
  949. for (int i = parasCount - 1; i >= 0; i--)
  950. para.Add((method.Params[i], Stack.Pop()));
  951. if (method.HasThis)
  952. para.Add((TypeUtils.ThisType(member.DeclaringType), Stack.Pop()));
  953. var tGen = (member.DeclaringType as TypeSpec)?.TryGetGenericInstSig()?.GenericArguments.ToList()
  954. ?? new List<TypeSig>();
  955. var gen = (member as MethodSpec)?.GenericInstMethodSig;
  956. para.Reverse();
  957. string expr;
  958. if (gen != null)
  959. {
  960. var genArgs = gen.GenericArguments;
  961. tGen.AddRange(genArgs);
  962. expr = $"{TypeUtils.EscapeTypeName(member.DeclaringType)}::{TypeUtils.EscapeMethodName(member, hasParamType: false)}<{string.Join(", ", gen.GenericArguments.Select(x => TypeUtils.EscapeTypeName(x, cppBasicType: true)))}>({string.Join(", ", para.Select((x, i) => CastExpression(x.destType, x.src, genArgs)))})";
  963. }
  964. else
  965. {
  966. expr = $"{ TypeUtils.EscapeTypeName(member.DeclaringType)}::{TypeUtils.EscapeMethodName(member, hasParamType: false)}({string.Join(", ", para.Select(x => CastExpression(x.destType, x.src, tGen)))})";
  967. }
  968. var stackType = TypeUtils.GetStackType(method.RetType, tGen);
  969. if (stackType.Code == StackTypeCode.Void)
  970. Stack.Push(stackType, expr);
  971. else
  972. Stack.Push(stackType, $"{expr}");
  973. }
  974. public void Callvirt()
  975. {
  976. var member = (IMethod)Op.Operand;
  977. var method = member.MethodSig;
  978. var para = new List<(TypeSig destType, StackEntry src)>();
  979. var parasCount = method.Params.Count;
  980. for (int i = parasCount - 1; i >= 0; i--)
  981. para.Add((method.Params[i], Stack.Pop()));
  982. Stack.Compute();
  983. para.Add((TypeUtils.ThisType(member.DeclaringType), Stack.Pop()));
  984. var tGen = (member.DeclaringType as TypeSpec)?.TryGetGenericInstSig()?.GenericArguments.ToList()
  985. ?? new List<TypeSig>();
  986. var gen = (member as MethodSpec)?.GenericInstMethodSig;
  987. para.Reverse();
  988. string expr;
  989. if (Stack.Constrained != null)
  990. {
  991. var thisTypeCode = para[0].src.Type.Code;
  992. if (thisTypeCode == StackTypeCode.O || thisTypeCode == StackTypeCode.Runtime)
  993. {
  994. Stack.Push(para[0].destType.ToTypeDefOrRef(), $"::natsu::ops::box(*{para[0].src.Expression})");
  995. para[0] = (para[0].destType, Stack.Pop());
  996. expr = $"{ TypeUtils.EscapeTypeName(Stack.Constrained)}::{TypeUtils.EscapeMethodName(member, hasParamType: false)}({string.Join(", ", para.Select(x => CastExpression(x.destType, x.src, tGen)))})";
  997. }
  998. else
  999. {
  1000. expr = $"{ TypeUtils.EscapeTypeName(Stack.Constrained)}::{TypeUtils.EscapeMethodName(member, hasParamType: false)}({string.Join(", ", para.Select(x => CastExpression(x.destType, x.src, tGen)))})";
  1001. }
  1002. Stack.Constrained = null;
  1003. }
  1004. else
  1005. {
  1006. expr = $"{para[0].src.Expression}.header().template vtable_as<typename {TypeUtils.EscapeTypeName(member.DeclaringType)}::VTable>()->{TypeUtils.EscapeMethodName(member)}({string.Join(", ", para.Select(x => CastExpression(x.destType, x.src, tGen)))})";
  1007. }
  1008. var stackType = TypeUtils.GetStackType(method.RetType, tGen);
  1009. if (stackType.Code == StackTypeCode.Void)
  1010. Stack.Push(stackType, expr);
  1011. else
  1012. Stack.Push(stackType, $"{expr}");
  1013. }
  1014. private static string CastExpression(TypeSig destType, StackEntry src, IList<TypeSig> genArgs = null)
  1015. {
  1016. if (src.Type.Name == "std::nullptr_t")
  1017. {
  1018. return $"{TypeUtils.EscapeVariableTypeName(destType, genArgs: genArgs)}(nullptr)";
  1019. }
  1020. else if (TypeUtils.IsSameType(destType, src.Type)
  1021. || destType.ElementType == src.Type.TypeSig.ElementType)
  1022. {
  1023. return $"{src.Expression}";
  1024. }
  1025. else if (destType.ElementType == ElementType.Ptr &&
  1026. src.Type.Code == StackTypeCode.Ref)
  1027. {
  1028. return $"{src.Expression}.get()";
  1029. }
  1030. else if (destType.ElementType != ElementType.ByRef &&
  1031. src.Type.Code == StackTypeCode.Ref)
  1032. {
  1033. return $"*{src.Expression}";
  1034. }
  1035. else
  1036. {
  1037. if (destType.IsValueType)
  1038. {
  1039. var typeDef = destType.ToTypeDefOrRef().ResolveTypeDef();
  1040. if (typeDef != null && typeDef.IsEnum)
  1041. {
  1042. //if (int.TryParse(src.Expression, out var intValue))
  1043. //{
  1044. // var field = typeDef.Fields.FirstOrDefault(x => x.HasConstant && Convert.ToInt32//(x.Constant.Value) == intValue);
  1045. // if (field != null)
  1046. // return $"{TypeUtils.EscapeTypeName(destType)}::{TypeUtils.EscapeIdentifier//(field.Name)}";
  1047. //}
  1048. return $"::natsu::ops::cast<{TypeUtils.EscapeVariableTypeName(destType, genArgs: genArgs)}>({src.Expression})";
  1049. }
  1050. else
  1051. {
  1052. return $"static_cast<{TypeUtils.EscapeVariableTypeName(destType, genArgs: genArgs)}>({src.Expression})";
  1053. }
  1054. }
  1055. else if (src.Type.Code != StackTypeCode.Ref)
  1056. {
  1057. return $"{TypeUtils.EscapeVariableTypeName(destType, genArgs: genArgs)}({src.Expression})";
  1058. }
  1059. else
  1060. {
  1061. return src.Expression;
  1062. }
  1063. }
  1064. }
  1065. private static string MakeAccessExpression(StackEntry src)
  1066. {
  1067. switch (src.Type.Code)
  1068. {
  1069. case StackTypeCode.Int32:
  1070. case StackTypeCode.Int64:
  1071. case StackTypeCode.NativeInt:
  1072. case StackTypeCode.F:
  1073. case StackTypeCode.ValueType:
  1074. return $"{src.Expression}.";
  1075. case StackTypeCode.O:
  1076. case StackTypeCode.Ref:
  1077. return $"{src.Expression}->";
  1078. case StackTypeCode.Runtime:
  1079. return $"::natsu::ops::access({src.Expression}).";
  1080. default:
  1081. throw new NotSupportedException();
  1082. }
  1083. }
  1084. private static string MakeUnsignedExpression(StackEntry src)
  1085. {
  1086. // Try parse literal
  1087. var exp = src.Expression;
  1088. if (uint.TryParse(exp, out var u4))
  1089. {
  1090. return $"{u4}U";
  1091. }
  1092. else if (ulong.TryParse(exp, out var u8))
  1093. {
  1094. return $"{u8}ULL";
  1095. }
  1096. else
  1097. {
  1098. if (src.Type.Code == StackTypeCode.O)
  1099. return src.Expression;
  1100. switch (src.Type.TypeSig.ElementType)
  1101. {
  1102. case ElementType.U:
  1103. case ElementType.U1:
  1104. case ElementType.U2:
  1105. case ElementType.U4:
  1106. case ElementType.U8:
  1107. case ElementType.Class:
  1108. case ElementType.Object:
  1109. case ElementType.String:
  1110. case ElementType.Array:
  1111. case ElementType.SZArray:
  1112. case ElementType.Boolean:
  1113. case ElementType.Ptr:
  1114. return src.Expression;
  1115. default:
  1116. return $"::natsu::ops::unsign({src.Expression})";
  1117. }
  1118. }
  1119. }
  1120. public void Nop()
  1121. {
  1122. // Writer.Ident(Ident).WriteLine("::natsu::nop();");
  1123. }
  1124. public void Ret()
  1125. {
  1126. if (Method.HasReturnType)
  1127. {
  1128. var value = Stack.Pop();
  1129. Writer.Ident(Ident).WriteLine($"return {CastExpression(Method.ReturnType, value)};");
  1130. }
  1131. else
  1132. {
  1133. Writer.Ident(Ident).WriteLine("return;");
  1134. }
  1135. }
  1136. public void Endfinally()
  1137. {
  1138. Writer.Ident(Ident).WriteLine("return;");
  1139. }
  1140. public void Throw()
  1141. {
  1142. var v1 = Stack.Pop();
  1143. Writer.Ident(Ident).WriteLine($"::natsu::ops::throw_({v1.Expression});");
  1144. }
  1145. public void Ldloc()
  1146. {
  1147. var local = Op.GetLocal(Method.Body.Variables.ToList());
  1148. Stack.Push(TypeUtils.GetStackType(local.Type), $"{TypeUtils.GetLocalName(local, Method)}", computed: false);
  1149. }
  1150. public void Ldloca()
  1151. {
  1152. var local = Op.GetLocal(Method.Body.Variables.ToList());
  1153. Stack.Push(TypeUtils.GetStackType(new ByRefSig(local.Type)), $"::natsu::ops::ref({TypeUtils.GetLocalName(local, Method)})", computed: true);
  1154. }
  1155. public void Stloc()
  1156. {
  1157. var local = Op.GetLocal(Method.Body.Variables.ToList());
  1158. var value = Stack.Pop();
  1159. Writer.Ident(Ident).WriteLine($"{TypeUtils.GetLocalName(local, Method)} = {CastExpression(local.Type, value)};");
  1160. }
  1161. public void Br()
  1162. {
  1163. var nextOp = (Instruction)Op.Operand;
  1164. BranchUnconditional(Ident, nextOp);
  1165. }
  1166. public void Leave()
  1167. {
  1168. var nextOp = (Instruction)Op.Operand;
  1169. BranchUnconditional(Ident, nextOp);
  1170. }
  1171. public void Unary(string op)
  1172. {
  1173. var v1 = Stack.Pop();
  1174. Stack.Push(v1.Type, $"{op}{v1.Expression}");
  1175. }
  1176. public void Binary(string op)
  1177. {
  1178. var v2 = Stack.Pop();
  1179. var v1 = Stack.Pop();
  1180. var type = TypeUtils.IsRefOrPtr(v1.Type) && TypeUtils.IsRefOrPtr(v2.Type)
  1181. ? TypeUtils.GetStackType(CorLibTypes.IntPtr)
  1182. : v1.Type;
  1183. if (op == "%" && v1.Type.Code == StackTypeCode.F)
  1184. {
  1185. if (v1.Type.TypeSig.ElementType == ElementType.R4)
  1186. Stack.Push(type, $"fmodf({v1.Expression}, {v2.Expression})");
  1187. else
  1188. Stack.Push(type, $"fmod({v1.Expression}, {v2.Expression})");
  1189. }
  1190. else
  1191. {
  1192. if (v1.Type.TypeSig.ElementType == ElementType.ValueType)
  1193. Stack.Push(v2.Type, $"({v1.Expression} {op} {v2.Expression})");
  1194. else
  1195. Stack.Push(type, $"({v1.Expression} {op} {v2.Expression})");
  1196. }
  1197. }
  1198. public void Binary_Un(string op)
  1199. {
  1200. var v2 = Stack.Pop();
  1201. var v1 = Stack.Pop();
  1202. var type = TypeUtils.IsRefOrPtr(v1.Type) && TypeUtils.IsRefOrPtr(v2.Type)
  1203. ? TypeUtils.GetStackType(CorLibTypes.UIntPtr)
  1204. : v1.Type;
  1205. if (op == "%" && v1.Type.Code == StackTypeCode.F)
  1206. {
  1207. if (v1.Type.TypeSig.ElementType == ElementType.R4)
  1208. Stack.Push(type, $"fmodf({v1.Expression}, {v2.Expression})");
  1209. else
  1210. Stack.Push(type, $"fmod({v1.Expression}, {v2.Expression})");
  1211. }
  1212. else
  1213. {
  1214. Stack.Push(type, $"({MakeUnsignedExpression(v1)} {op} {MakeUnsignedExpression(v2)})");
  1215. }
  1216. }
  1217. public void Compare(string op)
  1218. {
  1219. var v2 = Stack.Pop();
  1220. var v1 = Stack.Pop();
  1221. Stack.Push(CorLibTypes.Boolean, $"({v1.Expression} {op} {v2.Expression})");
  1222. }
  1223. public void Compare_Un(string op)
  1224. {
  1225. var v2 = Stack.Pop();
  1226. var v1 = Stack.Pop();
  1227. Stack.Push(CorLibTypes.Boolean, $"({MakeUnsignedExpression(v1)} {op} {MakeUnsignedExpression(v2)})");
  1228. }
  1229. private void BranchUnconditional(int ident, Instruction op)
  1230. {
  1231. Writer.Ident(Ident).WriteLine($"goto {ILUtils.GetLabel(Method, op, Block)};");
  1232. }
  1233. private void BranchCompare(string op)
  1234. {
  1235. var v2 = Stack.Pop();
  1236. var v1 = Stack.Pop();
  1237. var nextOp = (Instruction)Op.Operand;
  1238. Writer.Ident(Ident).WriteLine($"if ({v1.Expression} {op} {v2.Expression})");
  1239. Writer.Ident(Ident + 1).WriteLine($"goto {ILUtils.GetLabel(Method, nextOp, Block)};");
  1240. Writer.Ident(Ident).WriteLine("else");
  1241. Writer.Ident(Ident + 1).WriteLine($"goto {ILUtils.GetFallthroughLabel(Method, Op, Block)};");
  1242. }
  1243. private void BranchCompare_Un(string op)
  1244. {
  1245. var v2 = Stack.Pop();
  1246. var v1 = Stack.Pop();
  1247. var nextOp = (Instruction)Op.Operand;
  1248. Writer.Ident(Ident).WriteLine($"if ({MakeUnsignedExpression(v1)} {op} {MakeUnsignedExpression(v2)})");
  1249. Writer.Ident(Ident + 1).WriteLine($"goto {ILUtils.GetLabel(Method, nextOp, Block)};");
  1250. Writer.Ident(Ident).WriteLine("else");
  1251. Writer.Ident(Ident + 1).WriteLine($"goto {ILUtils.GetFallthroughLabel(Method, Op, Block)};");
  1252. }
  1253. private void BranchIf(string op)
  1254. {
  1255. var v1 = Stack.Pop();
  1256. var nextOp = (Instruction)Op.Operand;
  1257. Writer.Ident(Ident).WriteLine($"if ({op}{v1.Expression})");
  1258. Writer.Ident(Ident + 1).WriteLine($"goto {ILUtils.GetLabel(Method, nextOp, Block)};");
  1259. Writer.Ident(Ident).WriteLine("else");
  1260. Writer.Ident(Ident + 1).WriteLine($"goto {ILUtils.GetFallthroughLabel(Method, Op, Block)};");
  1261. }
  1262. public void Ldstr()
  1263. {
  1264. var value = (string)Op.Operand;
  1265. Stack.Push(CorLibTypes.String, $"::{ ModuleName}::user_string_{UserStrings.Count}.get()");
  1266. UserStrings.Add(value);
  1267. }
  1268. public void Ldsfld()
  1269. {
  1270. var field = (IField)Op.Operand;
  1271. string expr = Method.IsStaticConstructor && TypeUtils.IsSameType(Method.DeclaringType, field.DeclaringType)
  1272. ? TypeUtils.EscapeIdentifier(field.Name)
  1273. : "::natsu::static_holder<typename" + TypeUtils.EscapeTypeName(field.DeclaringType) + "::Static>::get()." + TypeUtils.EscapeIdentifier(field.Name);
  1274. var fieldType = field.FieldSig.Type;
  1275. if (Stack.PopVolatile())
  1276. expr += ".load()";
  1277. Stack.Push(TypeUtils.GetStackType(fieldType), $"{expr}");
  1278. }
  1279. public void Ldfld()
  1280. {
  1281. var target = Stack.Pop();
  1282. var field = (IField)Op.Operand;
  1283. var thisType = TypeUtils.ThisType(field.DeclaringType);
  1284. string expr = MakeAccessExpression(target) + TypeUtils.EscapeIdentifier(field.Name);
  1285. var fieldType = field.FieldSig.Type;
  1286. if (Stack.PopVolatile())
  1287. expr += ".load()";
  1288. Stack.Push(TypeUtils.GetStackType(fieldType), $"{expr}");
  1289. }
  1290. public void Ldflda()
  1291. {
  1292. var target = Stack.Pop();
  1293. var field = (IField)Op.Operand;
  1294. var thisType = TypeUtils.ThisType(field.DeclaringType);
  1295. var fieldType = field.FieldSig.Type;
  1296. if (TypeUtils.IsCppBasicType(field.DeclaringType))
  1297. {
  1298. if (target.Expression == "_this")
  1299. Stack.Push(TypeUtils.GetStackType(new ByRefSig(fieldType)), $"_this", computed: true);
  1300. else
  1301. Stack.Push(TypeUtils.GetStackType(new ByRefSig(fieldType)), $"::natsu::ops::ref({target.Expression})", computed: true);
  1302. }
  1303. else
  1304. {
  1305. string expr = MakeAccessExpression(target) + TypeUtils.EscapeIdentifier(field.Name);
  1306. Stack.Push(TypeUtils.GetStackType(new ByRefSig(fieldType)), $"::natsu::ops::ref({expr})", computed: true);
  1307. }
  1308. }
  1309. public void Ldsflda()
  1310. {
  1311. var field = (IField)Op.Operand;
  1312. var fieldType = field.FieldSig.Type;
  1313. string expr = Method.IsStaticConstructor && TypeUtils.IsSameType(Method.DeclaringType, field.DeclaringType)
  1314. ? TypeUtils.EscapeIdentifier(field.Name)
  1315. : "::natsu::static_holder<typename" + TypeUtils.EscapeTypeName(field.DeclaringType) + "::Static>::get()." + TypeUtils.EscapeIdentifier(field.Name);
  1316. Stack.Push(TypeUtils.GetStackType(new ByRefSig(fieldType)), $"::natsu::ops::ref({expr})", computed: true);
  1317. }
  1318. public void Stsfld()
  1319. {
  1320. if (Method.IsStaticConstructor && Method.DeclaringType.Name.Contains("List"))
  1321. ;
  1322. var value = Stack.Pop();
  1323. var field = (IField)Op.Operand;
  1324. if (Method.IsStaticConstructor && Method.DeclaringType.FullName.Contains("List"))
  1325. ;
  1326. string expr = Method.IsStaticConstructor && TypeUtils.IsSameType(Method.DeclaringType, field.DeclaringType)
  1327. ? TypeUtils.EscapeIdentifier(field.Name)
  1328. : "::natsu::static_holder<typename" + TypeUtils.EscapeTypeName(field.DeclaringType) + "::Static>::get()." + TypeUtils.EscapeIdentifier(field.Name);
  1329. var fieldType = field.FieldSig.Type;
  1330. if (Stack.PopVolatile())
  1331. Writer.Ident(Ident).WriteLine($"{expr}.store({CastExpression(fieldType, value)});");
  1332. else
  1333. Writer.Ident(Ident).WriteLine($"{expr} = {CastExpression(fieldType, value)};");
  1334. }
  1335. public void Stfld()
  1336. {
  1337. var value = Stack.Pop();
  1338. var target = Stack.Pop();
  1339. var field = (IField)Op.Operand;
  1340. var thisType = TypeUtils.ThisType(field.DeclaringType);
  1341. string expr = MakeAccessExpression(target) + TypeUtils.EscapeIdentifier(field.Name);
  1342. var fieldType = field.FieldSig.Type;
  1343. if (Stack.PopVolatile())
  1344. Writer.Ident(Ident).WriteLine($"{expr}.store({CastExpression(fieldType, value)});");
  1345. else
  1346. Writer.Ident(Ident).WriteLine($"{expr} = {CastExpression(fieldType, value)};");
  1347. }
  1348. public void Newarr()
  1349. {
  1350. var type = (ITypeDefOrRef)Op.Operand;
  1351. var len = Stack.Pop();
  1352. Stack.Push(new SZArraySig(type.ToTypeSig()).ToTypeDefOrRef(), $"::natsu::gc_new_array<{TypeUtils.EscapeTypeName(type, cppBasicType: true)}>({len.Expression})");
  1353. }
  1354. public void Initobj()
  1355. {
  1356. var type = (ITypeDefOrRef)Op.Operand;
  1357. var addr = Stack.Pop();
  1358. Writer.Ident(Ident).WriteLine($"::natsu::ops::initobj<{TypeUtils.EscapeVariableTypeName(type)}>({addr.Expression});");
  1359. }
  1360. public void Newobj()
  1361. {
  1362. var member = (IMethod)Op.Operand;
  1363. var method = member.MethodSig;
  1364. var para = new List<(TypeSig destType, StackEntry src)>();
  1365. var parasCount = method.Params.Count;
  1366. for (int i = parasCount - 1; i >= 0; i--)
  1367. para.Add((method.Params[i], Stack.Pop()));
  1368. para.Reverse();
  1369. var genSig = member.DeclaringType.TryGetGenericInstSig();
  1370. var expr = $"::natsu::ops::newobj<{TypeUtils.EscapeTypeName(member.DeclaringType, cppBasicType: true)}>({string.Join(", ", para.Select(x => CastExpression(x.destType, x.src, genSig?.GenericArguments)))})";
  1371. Stack.Push(TypeUtils.GetStackType(member.DeclaringType.ToTypeSig()), expr);
  1372. }
  1373. public void Ldobj()
  1374. {
  1375. var type = (ITypeDefOrRef)Op.Operand;
  1376. var addr = Stack.Pop();
  1377. Stack.Push(TypeUtils.GetStackType(type.ToTypeSig()), $"*{addr.Expression}");
  1378. }
  1379. public void Stobj()
  1380. {
  1381. var type = (ITypeDefOrRef)Op.Operand;
  1382. var src = Stack.Pop();
  1383. var dest = Stack.Pop();
  1384. Writer.Ident(Ident).WriteLine($"*{dest.Expression} = {src.Expression};");
  1385. }
  1386. public void Ldtoken()
  1387. {
  1388. var type = (ITypeDefOrRef)Op.Operand;
  1389. Stack.Push(CorLibTypes.Object, $"::natsu::ops::ldtoken_type<{TypeUtils.EscapeTypeName(type)}>()");
  1390. }
  1391. public void Isinst()
  1392. {
  1393. var type = (ITypeDefOrRef)Op.Operand;
  1394. var obj = Stack.Pop();
  1395. Stack.Push(TypeUtils.GetStackType(StackTypeCode.O, type.ToTypeSig()), $"::natsu::ops::isinst<{TypeUtils.EscapeTypeName(type, cppBasicType: true)}>({obj.Expression})");
  1396. }
  1397. public void Unbox_Any()
  1398. {
  1399. var type = (ITypeDefOrRef)Op.Operand;
  1400. var obj = Stack.Pop();
  1401. Stack.Push(TypeUtils.GetStackType(type.ToTypeSig()), $"::natsu::ops::unbox_any<{TypeUtils.EscapeTypeName(type, cppBasicType: true)}>({obj.Expression})");
  1402. }
  1403. public void Unbox()
  1404. {
  1405. var type = (ITypeDefOrRef)Op.Operand;
  1406. var obj = Stack.Pop();
  1407. Stack.Push(TypeUtils.GetStackType(new ByRefSig(type.ToTypeSig())), $"::natsu::ops::unbox<{TypeUtils.EscapeTypeName(type, cppBasicType: true)}>({obj.Expression})");
  1408. }
  1409. public void Castclass()
  1410. {
  1411. var type = (ITypeDefOrRef)Op.Operand;
  1412. var obj = Stack.Pop();
  1413. Stack.Push(TypeUtils.GetStackType(type.ToTypeSig()), $"::natsu::ops::castclass<{TypeUtils.EscapeTypeName(type, cppBasicType: true)}>({obj.Expression})");
  1414. }
  1415. public void Ldlen()
  1416. {
  1417. var target = Stack.Pop();
  1418. Stack.Push(CorLibTypes.UIntPtr, $"{target.Expression}->length()");
  1419. }
  1420. public void Localloc()
  1421. {
  1422. var size = Stack.Pop();
  1423. Stack.Push(CorLibTypes.UIntPtr, $"natsu_alloca({size.Expression})");
  1424. }
  1425. private void Conversion(TypeSig stackType, string type)
  1426. {
  1427. var value = Stack.Pop();
  1428. var expr = value.Expression;
  1429. if (TypeUtils.IsRefOrPtr(value.Type))
  1430. expr += ".ptr_";
  1431. string destTypeName = null;
  1432. if (stackType.ElementType == ElementType.I ||
  1433. stackType.ElementType == ElementType.U)
  1434. {
  1435. if (TypeUtils.IsRefOrPtr(value.Type))
  1436. {
  1437. destTypeName = stackType.ElementType switch
  1438. {
  1439. ElementType.I => "reinterpret_cast<intptr_t>",
  1440. ElementType.U => "reinterpret_cast<uintptr_t>",
  1441. };
  1442. }
  1443. else
  1444. {
  1445. destTypeName = stackType.ElementType switch
  1446. {
  1447. ElementType.I => "static_cast<intptr_t>",
  1448. ElementType.U => "static_cast<uintptr_t>",
  1449. };
  1450. }
  1451. }
  1452. else
  1453. {
  1454. switch (stackType.ElementType)
  1455. {
  1456. case ElementType.I1:
  1457. case ElementType.I2:
  1458. case ElementType.I4:
  1459. case ElementType.I8:
  1460. case ElementType.U1:
  1461. case ElementType.U2:
  1462. case ElementType.U4:
  1463. case ElementType.U8:
  1464. if (TypeUtils.IsRefOrPtr(value.Type))
  1465. destTypeName = $"reinterpret_cast<{TypeUtils.EscapeVariableTypeName(stackType)}>";
  1466. break;
  1467. }
  1468. }
  1469. destTypeName = destTypeName ?? $"static_cast<{TypeUtils.EscapeVariableTypeName(stackType)}>";
  1470. Stack.Push(stackType, $"{destTypeName}({expr})");
  1471. }
  1472. private void Ldind(TypeSig stackType)
  1473. {
  1474. var addr = Stack.Pop();
  1475. if (addr.Type.TypeSig.ElementType == ElementType.ByRef ||
  1476. addr.Type.TypeSig.ElementType == ElementType.Ptr)
  1477. {
  1478. var actualType = addr.Type.TypeSig.Next;
  1479. if (TypeUtils.IsSameType(actualType.ToTypeDefOrRef(), stackType.ToTypeDefOrRef()))
  1480. {
  1481. Stack.Push(stackType, $"*{addr.Expression}");
  1482. return;
  1483. }
  1484. }
  1485. Stack.Push(stackType, $"::natsu::ops::ldind<{TypeUtils.EscapeVariableTypeName(stackType)}>({addr.Expression})");
  1486. }
  1487. private void Stind(string type)
  1488. {
  1489. var value = Stack.Pop();
  1490. var addr = Stack.Pop();
  1491. Writer.Ident(Ident).WriteLine($"*{addr.Expression} = {value.Expression};");
  1492. }
  1493. private void Ldelem(TypeSig stackType, string type)
  1494. {
  1495. var index = Stack.Pop();
  1496. var array = Stack.Pop();
  1497. Stack.Push(stackType, $"{array.Expression}->at({index.Expression})");
  1498. }
  1499. private void Stelem(string type)
  1500. {
  1501. var value = Stack.Pop();
  1502. var index = Stack.Pop();
  1503. var array = Stack.Pop();
  1504. //Writer.Ident(Ident).WriteLine($"::natsu::ops::stelem_{type}({array.Expression}, {index.Expression}, {value.Expression});");
  1505. Writer.Ident(Ident).WriteLine($"{array.Expression}->at({index.Expression}) = {value.Expression};");
  1506. }
  1507. public void Ldelem()
  1508. {
  1509. var type = (ITypeDefOrRef)Op.Operand;
  1510. var index = Stack.Pop();
  1511. var array = Stack.Pop();
  1512. Stack.Push(TypeUtils.GetStackType(type.ToTypeSig()), $"{array.Expression}->at({index.Expression})");
  1513. }
  1514. public void Stelem()
  1515. {
  1516. var type = (ITypeDefOrRef)Op.Operand;
  1517. var value = Stack.Pop();
  1518. var index = Stack.Pop();
  1519. var array = Stack.Pop();
  1520. Writer.Ident(Ident).WriteLine($"{array.Expression}->at({index.Expression}) = {value.Expression};");
  1521. }
  1522. public void Ldelema()
  1523. {
  1524. var type = (ITypeDefOrRef)Op.Operand;
  1525. var index = Stack.Pop();
  1526. var array = Stack.Pop();
  1527. Stack.Push(TypeUtils.GetStackType(new ByRefSig(type.ToTypeSig())), $"{array.Expression}->ref_at({index.Expression})");
  1528. }
  1529. public void Box()
  1530. {
  1531. var type = (ITypeDefOrRef)Op.Operand;
  1532. var value = Stack.Pop();
  1533. Stack.Push(CorLibTypes.Object, $"::natsu::ops::box({CastExpression(type.ToTypeSig(), value)})");
  1534. }
  1535. public void Ldnull()
  1536. {
  1537. Stack.Push(new StackType { Code = StackTypeCode.O, TypeSig = CorLibTypes.Object, Name = "std::nullptr_t" }, "nullptr");
  1538. }
  1539. public void Dup()
  1540. {
  1541. Stack.Dup();
  1542. }
  1543. public void Ldftn()
  1544. {
  1545. var member = (IMethod)Op.Operand;
  1546. var method = member.MethodSig;
  1547. var tGen = (member.DeclaringType as TypeSpec)?.TryGetGenericInstSig()?.GenericArguments.ToList()
  1548. ?? new List<TypeSig>();
  1549. var gen = (member as MethodSpec)?.GenericInstMethodSig;
  1550. string expr;
  1551. if (gen != null)
  1552. {
  1553. var genArgs = gen.GenericArguments;
  1554. tGen.AddRange(genArgs);
  1555. expr = $"{TypeUtils.EscapeTypeName(member.DeclaringType)}::{TypeUtils.EscapeMethodName(member, hasParamType: false)}<{string.Join(", ", gen.GenericArguments.Select(x => TypeUtils.EscapeTypeName(x)))}>";
  1556. }
  1557. else
  1558. {
  1559. expr = $"{ TypeUtils.EscapeTypeName(member.DeclaringType)}::{TypeUtils.EscapeMethodName(member, hasParamType: false)}";
  1560. }
  1561. Stack.Push(CorLibTypes.IntPtr, $"::natsu::ops::ldftn({expr})");
  1562. }
  1563. public void Ldvirtftn()
  1564. {
  1565. var member = (IMethod)Op.Operand;
  1566. var method = member.MethodSig;
  1567. var tGen = (member.DeclaringType as TypeSpec)?.TryGetGenericInstSig()?.GenericArguments.ToList()
  1568. ?? new List<TypeSig>();
  1569. var gen = (member as MethodSpec)?.GenericInstMethodSig;
  1570. string expr;
  1571. if (gen != null)
  1572. {
  1573. throw new NotSupportedException();
  1574. }
  1575. else
  1576. {
  1577. var obj = Stack.Pop();
  1578. expr = $"{obj.Expression}.header().template vtable_as<typename {TypeUtils.EscapeTypeName(member.DeclaringType)}::VTable>()->{TypeUtils.EscapeMethodName(member)}";
  1579. }
  1580. Stack.Push(CorLibTypes.IntPtr, $"::natsu::ops::ldftn({expr})");
  1581. }
  1582. public void Switch()
  1583. {
  1584. var instructions = (Instruction[])Op.Operand;
  1585. var v1 = Stack.Pop();
  1586. Writer.Ident(Ident).WriteLine($"switch ({v1.Expression})");
  1587. Writer.Ident(Ident).WriteLine("{");
  1588. for (int i = 0; i < instructions.Length; i++)
  1589. {
  1590. Writer.Ident(Ident + 1).WriteLine($"case {i}:");
  1591. Writer.Ident(Ident + 2).WriteLine($"goto {ILUtils.GetLabel(Method, instructions[i], Block)};");
  1592. }
  1593. Writer.Ident(Ident + 1).WriteLine("default:");
  1594. Writer.Ident(Ident + 2).WriteLine($"goto {ILUtils.GetFallthroughLabel(Method, Op, Block)};");
  1595. Writer.Ident(Ident).WriteLine("}");
  1596. }
  1597. public void Sizeof()
  1598. {
  1599. var type = (ITypeDefOrRef)Op.Operand;
  1600. Stack.Push(CorLibTypes.Int32, $"sizeof({TypeUtils.EscapeTypeName(type)})");
  1601. }
  1602. public void Pop()
  1603. {
  1604. Stack.Compute();
  1605. Stack.Pop();
  1606. }
  1607. }
  1608. }