rawasmtext.pas 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909
  1. {
  2. Copyright (c) 1998-2008 by Carl Eric Codere and Peter Vreman
  3. Copyright (c) 2024 by Nikolay Nikolov
  4. Does the parsing for the WebAssembly styled inline assembler.
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. Unit rawasmtext;
  19. {$i fpcdefs.inc}
  20. Interface
  21. uses
  22. cclasses,
  23. globtype,
  24. rasm,rawasm,
  25. aasmbase,cpubase;
  26. type
  27. tasmtoken = (
  28. AS_NONE,AS_LPAREN,AS_RPAREN,AS_ID,AS_END,AS_OPCODE,AS_INTNUM,
  29. AS_REALNUM,AS_STRING,AS_PARAM,AS_RESULT,AS_THEN,AS_ELSE,AS_TYPE,AS_VALTYPE
  30. );
  31. tasmkeyword = string[10];
  32. const
  33. token2str : array[tasmtoken] of tasmkeyword=(
  34. '','(',')','identifier','end','opcode','integer','float','string',
  35. 'param','result','then','else','type','valtype');
  36. type
  37. { twasmreader }
  38. twasmreader = class(tasmreader)
  39. private
  40. actwasmbasictype: TWasmBasicType;
  41. actasmpattern_origcase: string;
  42. actasmtoken : tasmtoken;
  43. prevasmtoken : tasmtoken;
  44. actinttoken : aint;
  45. actfloattoken : double;
  46. procedure SetupTables;
  47. procedure GetToken;
  48. function consume(t : tasmtoken):boolean;
  49. function is_asmopcode(const s: string):boolean;
  50. function is_valtype(const s: string):boolean;
  51. procedure HandleInstruction;
  52. procedure HandleFoldedInstruction;
  53. function HandlePlainInstruction: TWasmInstruction;
  54. procedure HandleBlockInstruction;virtual;abstract;
  55. public
  56. function Assemble: tlinkedlist;override;
  57. end;
  58. Implementation
  59. uses
  60. { helpers }
  61. cutils,
  62. { global }
  63. globals,verbose,
  64. systems,
  65. { aasm }
  66. cpuinfo,aasmtai,aasmdata,aasmcpu,
  67. { symtable }
  68. symconst,symbase,symtype,symsym,symtable,symdef,symutil,
  69. { parser }
  70. scanner,pbase,
  71. procinfo,
  72. rabase,rautils,
  73. cgbase,cgutils,cgobj,
  74. { wasm }
  75. itcpuwasm
  76. ;
  77. {*****************************************************************************
  78. twasmreader
  79. *****************************************************************************}
  80. procedure twasmreader.SetupTables;
  81. var
  82. i: TAsmOp;
  83. begin
  84. iasmops:=TFPHashList.create;
  85. for i:=firstop to lastop do
  86. if wasm_op2str[i]<>'end' then
  87. iasmops.Add(wasm_op2str[i],Pointer(PtrInt(i)));
  88. end;
  89. procedure twasmreader.GetToken;
  90. var
  91. has_sign, is_hex, is_float: Boolean;
  92. function GetIntToken: aint;
  93. var
  94. s: string;
  95. u64: UInt64;
  96. begin
  97. s:=actasmpattern;
  98. if has_sign and (s[1]='-') then
  99. begin
  100. delete(s,1,1);
  101. if is_hex then
  102. begin
  103. delete(s,1,2);
  104. Val('$'+s,u64);
  105. end
  106. else
  107. Val(s,u64);
  108. {$push} {$R-}{$Q-}
  109. result:=aint(-u64);
  110. {$pop}
  111. end
  112. else
  113. begin
  114. if has_sign then
  115. delete(s,1,1);
  116. if is_hex then
  117. begin
  118. delete(s,1,2);
  119. Val('$'+s,u64);
  120. end
  121. else
  122. Val(s,u64);
  123. result:=aint(u64);
  124. end;
  125. end;
  126. function GetFloatToken: double;
  127. var
  128. s: string;
  129. begin
  130. s:=actasmpattern;
  131. if is_hex then
  132. begin
  133. { TODO: parse hex floats }
  134. internalerror(2024071501);
  135. end
  136. else
  137. Val(s,result);
  138. end;
  139. var
  140. len: Integer;
  141. tmpS: string;
  142. tmpI, tmpCode: Integer;
  143. begin
  144. c:=scanner.c;
  145. { save old token and reset new token }
  146. prevasmtoken:=actasmtoken;
  147. actasmtoken:=AS_NONE;
  148. { reset }
  149. actasmpattern:='';
  150. { while space, tab, new line or comment, continue scan... }
  151. while c in [' ',#9,#13,#10] do
  152. begin
  153. c:=current_scanner.asmgetchar;
  154. case c of
  155. ';':
  156. begin
  157. c:=current_scanner.asmgetchar;
  158. case c of
  159. { ;; comment until end of line }
  160. ';':
  161. begin
  162. { skip until end of line }
  163. repeat
  164. c:=current_scanner.asmgetchar;
  165. until c in [#13,#10];
  166. end;
  167. else
  168. current_scanner.illegal_char(c);
  169. end;
  170. end;
  171. '(':
  172. begin
  173. current_scanner.gettokenpos;
  174. c:=current_scanner.asmgetchar;
  175. case c of
  176. { (; block comment ;) }
  177. ';':
  178. begin
  179. { skip until ;) }
  180. repeat
  181. c:=current_scanner.asmgetchar;
  182. if c=';' then
  183. begin
  184. c:=current_scanner.asmgetchar;
  185. if c=')' then
  186. begin
  187. c:=current_scanner.asmgetchar;
  188. break;
  189. end;
  190. end;
  191. until false;
  192. end;
  193. else
  194. begin
  195. actasmtoken:=AS_LPAREN;
  196. exit;
  197. end;
  198. end;
  199. end;
  200. end;
  201. end;
  202. current_scanner.gettokenpos;
  203. case c of
  204. ')':
  205. begin
  206. c:=current_scanner.asmgetchar;
  207. actasmtoken:=AS_RPAREN;
  208. end;
  209. '$','a'..'z','A'..'Z':
  210. begin
  211. len:=0;
  212. while c in ['A'..'Z','a'..'z','0'..'9',
  213. '!','#','$','%','&','''','*','+','-','.','/',
  214. ':','<','=','>','?','@','\','^','_','`','|','~'] do
  215. begin
  216. inc(len);
  217. actasmpattern[len]:=c;
  218. c:=current_scanner.asmgetchar;
  219. end;
  220. actasmpattern[0]:=chr(len);
  221. actasmpattern_origcase:=actasmpattern;
  222. if actasmpattern[1]='$' then
  223. actasmtoken:=AS_ID
  224. else if is_asmopcode(actasmpattern) or
  225. is_valtype(actasmpattern) then
  226. exit
  227. else if upper(actasmpattern) = 'END' then
  228. begin
  229. uppervar(actasmpattern);
  230. actasmtoken:=AS_END;
  231. exit;
  232. end
  233. else
  234. begin
  235. message1(asmr_e_unknown_opcode,actasmpattern);
  236. actasmtoken:=AS_NONE;
  237. end;
  238. end;
  239. '0'..'9','+','-':
  240. begin
  241. len:=0;
  242. has_sign:=false;
  243. is_hex:=false;
  244. is_float:=false;
  245. if c in ['+','-'] then
  246. begin
  247. has_sign:=true;
  248. inc(len);
  249. actasmpattern[len]:=c;
  250. c:=current_scanner.asmgetchar;
  251. end;
  252. if c='0' then
  253. begin
  254. inc(len);
  255. actasmpattern[len]:=c;
  256. c:=current_scanner.asmgetchar;
  257. if c='x' then
  258. begin
  259. is_hex:=true;
  260. inc(len);
  261. actasmpattern[len]:=c;
  262. c:=current_scanner.asmgetchar;
  263. end;
  264. end;
  265. if is_hex then
  266. begin
  267. while c in ['0'..'9','a'..'f','A'..'F'] do
  268. begin
  269. inc(len);
  270. actasmpattern[len]:=c;
  271. c:=current_scanner.asmgetchar;
  272. end;
  273. end
  274. else
  275. begin
  276. while c in ['0'..'9'] do
  277. begin
  278. inc(len);
  279. actasmpattern[len]:=c;
  280. c:=current_scanner.asmgetchar;
  281. end;
  282. end;
  283. if c='.' then
  284. begin
  285. is_float:=true;
  286. inc(len);
  287. actasmpattern[len]:=c;
  288. c:=current_scanner.asmgetchar;
  289. { parse the fractional part }
  290. if is_hex then
  291. begin
  292. while c in ['0'..'9','a'..'f','A'..'F'] do
  293. begin
  294. inc(len);
  295. actasmpattern[len]:=c;
  296. c:=current_scanner.asmgetchar;
  297. end;
  298. end
  299. else
  300. begin
  301. while c in ['0'..'9'] do
  302. begin
  303. inc(len);
  304. actasmpattern[len]:=c;
  305. c:=current_scanner.asmgetchar;
  306. end;
  307. end;
  308. end;
  309. if (is_hex and (c in ['p','P'])) or
  310. ((not is_hex) and (c in ['e','E'])) then
  311. begin
  312. inc(len);
  313. actasmpattern[len]:=c;
  314. c:=current_scanner.asmgetchar;
  315. if c in ['+','-'] then
  316. begin
  317. inc(len);
  318. actasmpattern[len]:=c;
  319. c:=current_scanner.asmgetchar;
  320. end;
  321. while c in ['0'..'9'] do
  322. begin
  323. inc(len);
  324. actasmpattern[len]:=c;
  325. c:=current_scanner.asmgetchar;
  326. end;
  327. end;
  328. actasmpattern[0]:=chr(len);
  329. if is_float then
  330. begin
  331. actasmtoken:=AS_REALNUM;
  332. actfloattoken:=GetFloatToken;
  333. end
  334. else
  335. begin
  336. actasmtoken:=AS_INTNUM;
  337. actinttoken:=GetIntToken;
  338. end;
  339. end;
  340. '"':
  341. begin
  342. actasmpattern:='';
  343. repeat
  344. c:=current_scanner.asmgetchar;
  345. case c of
  346. '\' :
  347. begin
  348. c:=current_scanner.asmgetchar;
  349. case c of
  350. 't':
  351. begin
  352. actasmpattern:=actasmpattern+#9;
  353. c:=current_scanner.asmgetchar;
  354. end;
  355. 'n':
  356. begin
  357. actasmpattern:=actasmpattern+#10;
  358. c:=current_scanner.asmgetchar;
  359. end;
  360. 'r':
  361. begin
  362. actasmpattern:=actasmpattern+#13;
  363. c:=current_scanner.asmgetchar;
  364. end;
  365. '"':
  366. begin
  367. actasmpattern:=actasmpattern+'"';
  368. c:=current_scanner.asmgetchar;
  369. end;
  370. '''':
  371. begin
  372. actasmpattern:=actasmpattern+'''';
  373. c:=current_scanner.asmgetchar;
  374. end;
  375. '\':
  376. begin
  377. actasmpattern:=actasmpattern+'\';
  378. c:=current_scanner.asmgetchar;
  379. end;
  380. 'u':
  381. begin
  382. tmpS:='';
  383. c:=current_scanner.asmgetchar;
  384. while c in ['0'..'9','a'..'f','A'..'F'] do
  385. begin
  386. tmpS:=tmpS+c;
  387. c:=current_scanner.asmgetchar;
  388. end;
  389. if tmpS<>'' then
  390. begin
  391. Val('$'+tmpS,tmpI,tmpCode);
  392. if (tmpI<$D800) or ((tmpI>=$E000) and (tmpI<$110000)) then
  393. begin
  394. if tmpI<=$7F then
  395. actasmpattern:=actasmpattern+Chr(tmpI)
  396. else if tmpI<=$7FF then
  397. actasmpattern:=actasmpattern+
  398. Chr(%11000000 or (tmpI shr 6))+
  399. Chr(%10000000 or (tmpI and $3F))
  400. else if tmpI<=$FFFF then
  401. actasmpattern:=actasmpattern+
  402. Chr(%11100000 or (tmpI shr 12))+
  403. Chr(%10000000 or ((tmpI shr 6) and $3F))+
  404. Chr(%10000000 or (tmpI and $3F))
  405. else
  406. actasmpattern:=actasmpattern+
  407. Chr(%11110000 or (tmpI shr 18))+
  408. Chr(%10000000 or ((tmpI shr 12) and $3F))+
  409. Chr(%10000000 or ((tmpI shr 6) and $3F))+
  410. Chr(%10000000 or (tmpI and $3F))
  411. end
  412. else
  413. Message1(asmr_e_escape_seq_ignored,'u'+tmpS);
  414. end
  415. else
  416. Message1(asmr_e_escape_seq_ignored,'u');
  417. end;
  418. '0'..'9','a'..'f','A'..'F':
  419. begin
  420. tmpS:=c;
  421. c:=current_scanner.asmgetchar;
  422. if c in ['0'..'9','a'..'f','A'..'F'] then
  423. begin
  424. tmpS:=tmpS+c;
  425. c:=current_scanner.asmgetchar;
  426. Val('$'+tmpS,tmpI,tmpCode);
  427. actasmpattern:=actasmpattern+Chr(tmpI);
  428. end
  429. else
  430. begin
  431. Message1(asmr_e_escape_seq_ignored,tmpS+c);
  432. c:=current_scanner.asmgetchar;
  433. end;
  434. end;
  435. else
  436. begin
  437. Message1(asmr_e_escape_seq_ignored,c);
  438. c:=current_scanner.asmgetchar;
  439. end;
  440. end;
  441. end;
  442. '"' :
  443. begin
  444. c:=current_scanner.asmgetchar;
  445. break;
  446. end;
  447. #10,#13:
  448. Message(scan_f_string_exceeds_line);
  449. #0..#9,#11,#12,#14..#31,#127:
  450. current_scanner.illegal_char(c);
  451. else
  452. actasmpattern:=actasmpattern+c;
  453. end;
  454. until false;
  455. actasmtoken:=AS_STRING;
  456. exit;
  457. end;
  458. else
  459. current_scanner.illegal_char(c);
  460. end;
  461. end;
  462. function twasmreader.consume(t: tasmtoken): boolean;
  463. begin
  464. Consume:=true;
  465. if t<>actasmtoken then
  466. begin
  467. Message2(scan_f_syn_expected,token2str[t],token2str[actasmtoken]);
  468. Consume:=false;
  469. end;
  470. repeat
  471. gettoken;
  472. until actasmtoken<>AS_NONE;
  473. end;
  474. function twasmreader.is_asmopcode(const s: string): boolean;
  475. begin
  476. actopcode:=tasmop(PtrUInt(iasmops.Find(s)));
  477. if actopcode<>A_NONE then
  478. begin
  479. actasmtoken:=AS_OPCODE;
  480. is_asmopcode:=true;
  481. end
  482. else
  483. is_asmopcode:=false;
  484. end;
  485. function twasmreader.is_valtype(const s: string): boolean;
  486. begin
  487. actwasmbasictype:=wbt_Unknown;
  488. case s of
  489. 'i32':
  490. actwasmbasictype:=wbt_i32;
  491. 'i64':
  492. actwasmbasictype:=wbt_i64;
  493. 'f32':
  494. actwasmbasictype:=wbt_f32;
  495. 'f64':
  496. actwasmbasictype:=wbt_f64;
  497. 'funcref':
  498. actwasmbasictype:=wbt_funcref;
  499. 'externref':
  500. actwasmbasictype:=wbt_externref;
  501. 'v128':
  502. actwasmbasictype:=wbt_v128;
  503. end;
  504. if actwasmbasictype<>wbt_Unknown then
  505. begin
  506. actasmtoken:=AS_VALTYPE;
  507. is_valtype:=true;
  508. end
  509. else
  510. is_valtype:=false;
  511. end;
  512. procedure twasmreader.HandleInstruction;
  513. begin
  514. case actasmtoken of
  515. AS_LPAREN:
  516. begin
  517. Consume(AS_LPAREN);
  518. HandleFoldedInstruction;
  519. end;
  520. AS_OPCODE:
  521. begin
  522. case actopcode of
  523. a_block,
  524. a_loop,
  525. a_if:
  526. HandleBlockInstruction;
  527. else
  528. HandlePlainInstruction;
  529. end;
  530. end;
  531. else
  532. {error};
  533. end;
  534. end;
  535. procedure twasmreader.HandleFoldedInstruction;
  536. var
  537. HasLabel, HasType, HasParam, HasResult, HasInstructions,
  538. HasThen, HasElse: Boolean;
  539. instr: TWasmInstruction;
  540. tmpS: string;
  541. begin
  542. //Consume(AS_LPAREN);
  543. case actasmtoken of
  544. AS_OPCODE:
  545. begin
  546. case actopcode of
  547. a_block,
  548. a_loop,
  549. a_if:
  550. begin
  551. Consume(AS_OPCODE);
  552. HasType:=False;
  553. HasParam:=False;
  554. HasResult:=False;
  555. HasInstructions:=False;
  556. HasThen:=False;
  557. HasElse:=False;
  558. instr:=TWasmInstruction.create(TWasmOperand);
  559. instr.opcode:=actopcode;
  560. HasLabel:=False;
  561. if actasmtoken=AS_ID then
  562. begin
  563. Consume(AS_ID);
  564. HasLabel:=True;
  565. end;
  566. repeat
  567. case actasmtoken of
  568. AS_LPAREN:
  569. begin
  570. Consume(AS_LPAREN);
  571. case actasmtoken of
  572. AS_TYPE:
  573. begin
  574. if HasElse or HasThen or HasInstructions or HasResult or HasParam or HasType then
  575. begin
  576. {TODO: error}
  577. end;
  578. Consume(AS_TYPE);
  579. //TODO: consume u32 or id
  580. Consume(actasmtoken);
  581. Consume(AS_RPAREN);
  582. end;
  583. AS_PARAM:
  584. begin
  585. if HasElse or HasThen or HasInstructions or HasResult then
  586. begin
  587. {TODO: error}
  588. end;
  589. Consume(AS_PARAM);
  590. if actasmtoken=AS_ID then
  591. begin
  592. tmpS:=actasmpattern;
  593. Consume(AS_ID);
  594. if actasmtoken=AS_VALTYPE then
  595. instr.AddParam(actasmpattern,actwasmbasictype);
  596. Consume(AS_VALTYPE);
  597. end
  598. else
  599. begin
  600. while actasmtoken<>AS_RPAREN do
  601. begin
  602. if actasmtoken=AS_VALTYPE then
  603. instr.AddParam('',actwasmbasictype);
  604. Consume(AS_VALTYPE);
  605. end;
  606. end;
  607. Consume(AS_RPAREN);
  608. end;
  609. AS_RESULT:
  610. begin
  611. if HasElse or HasThen or HasInstructions then
  612. begin
  613. {TODO: error}
  614. end;
  615. Consume(AS_RESULT);
  616. while actasmtoken<>AS_RPAREN do
  617. begin
  618. if actasmtoken=AS_VALTYPE then
  619. instr.AddResult(actwasmbasictype);
  620. Consume(AS_VALTYPE);
  621. end;
  622. Consume(AS_RPAREN);
  623. end;
  624. AS_THEN:
  625. begin
  626. if instr.opcode<>a_if then
  627. {error!};
  628. Consume(AS_THEN);
  629. HasThen:=True;
  630. while actasmtoken<>AS_RPAREN do
  631. HandleInstruction;
  632. Consume(AS_RPAREN);
  633. end;
  634. AS_ELSE:
  635. begin
  636. if instr.opcode<>a_if then
  637. {error!};
  638. Consume(AS_ELSE);
  639. HasElse:=True;
  640. while actasmtoken<>AS_RPAREN do
  641. HandleInstruction;
  642. Consume(AS_RPAREN);
  643. end;
  644. else
  645. begin
  646. HasInstructions:=True;
  647. HandleFoldedInstruction;
  648. end;
  649. end;
  650. end;
  651. else
  652. {todo: error};
  653. end;
  654. until false;
  655. end;
  656. else
  657. begin
  658. HandlePlainInstruction;
  659. {todo: parse next folded instructions, insert plain instruction after these}
  660. end;
  661. end;
  662. end;
  663. else
  664. {error}
  665. end;
  666. end;
  667. function twasmreader.HandlePlainInstruction: TWasmInstruction;
  668. begin
  669. result:=nil;
  670. case actasmtoken of
  671. AS_OPCODE:
  672. begin
  673. result:=TWasmInstruction.create(TWasmOperand);
  674. result.opcode:=actopcode;
  675. Consume(AS_OPCODE);
  676. case actopcode of
  677. { instructions, which require 0 operands }
  678. a_nop,
  679. a_unreachable,
  680. a_return,
  681. a_ref_is_null,
  682. a_drop,
  683. a_memory_size,
  684. a_memory_grow,
  685. a_memory_fill,
  686. a_memory_copy,
  687. a_i32_clz,a_i32_ctz,a_i32_popcnt,a_i32_add,a_i32_sub,a_i32_mul,a_i32_div_s,a_i32_div_u,a_i32_rem_s,a_i32_rem_u,a_i32_and,a_i32_or,a_i32_xor,a_i32_shl,a_i32_shr_s,a_i32_shr_u,a_i32_rotl,a_i32_rotr,
  688. a_i64_clz,a_i64_ctz,a_i64_popcnt,a_i64_add,a_i64_sub,a_i64_mul,a_i64_div_s,a_i64_div_u,a_i64_rem_s,a_i64_rem_u,a_i64_and,a_i64_or,a_i64_xor,a_i64_shl,a_i64_shr_s,a_i64_shr_u,a_i64_rotl,a_i64_rotr,
  689. a_f32_abs,a_f32_neg,a_f32_ceil,a_f32_floor,a_f32_trunc,a_f32_nearest,a_f32_sqrt,a_f32_add,a_f32_sub,a_f32_mul,a_f32_div,a_f32_min,a_f32_max,a_f32_copysign,
  690. a_f64_abs,a_f64_neg,a_f64_ceil,a_f64_floor,a_f64_trunc,a_f64_nearest,a_f64_sqrt,a_f64_add,a_f64_sub,a_f64_mul,a_f64_div,a_f64_min,a_f64_max,a_f64_copysign,
  691. a_i32_eqz,a_i32_eq,a_i32_ne,a_i32_lt_s,a_i32_lt_u,a_i32_gt_s,a_i32_gt_u,a_i32_le_s,a_i32_le_u,a_i32_ge_s,a_i32_ge_u,
  692. a_i64_eqz,a_i64_eq,a_i64_ne,a_i64_lt_s,a_i64_lt_u,a_i64_gt_s,a_i64_gt_u,a_i64_le_s,a_i64_le_u,a_i64_ge_s,a_i64_ge_u,
  693. a_f32_eq,a_f32_ne,a_f32_lt,a_f32_gt,a_f32_le,a_f32_ge,
  694. a_f64_eq,a_f64_ne,a_f64_lt,a_f64_gt,a_f64_le,a_f64_ge,
  695. a_i32_wrap_i64,
  696. a_i32_trunc_f32_s,
  697. a_i32_trunc_f32_u,
  698. a_i32_trunc_f64_s,
  699. a_i32_trunc_f64_u,
  700. a_i32_trunc_sat_f32_s,
  701. a_i32_trunc_sat_f32_u,
  702. a_i32_trunc_sat_f64_s,
  703. a_i32_trunc_sat_f64_u,
  704. a_i64_extend_i32_s,
  705. a_i64_extend_i32_u,
  706. a_i64_trunc_f32_s,
  707. a_i64_trunc_f32_u,
  708. a_i64_trunc_f64_s,
  709. a_i64_trunc_f64_u,
  710. a_i64_trunc_sat_f32_s,
  711. a_i64_trunc_sat_f32_u,
  712. a_i64_trunc_sat_f64_u,
  713. a_i64_trunc_sat_f64_s,
  714. a_f32_convert_i32_s,
  715. a_f32_convert_i32_u,
  716. a_f32_convert_i64_s,
  717. a_f32_convert_i64_u,
  718. a_f32_demote_f64,
  719. a_f64_convert_i32_s,
  720. a_f64_convert_i32_u,
  721. a_f64_convert_i64_s,
  722. a_f64_convert_i64_u,
  723. a_f64_promote_f32,
  724. a_i32_reinterpret_f32,
  725. a_i64_reinterpret_f64,
  726. a_f32_reinterpret_i32,
  727. a_f64_reinterpret_i64,
  728. a_i32_extend8_s,
  729. a_i32_extend16_s,
  730. a_i64_extend8_s,
  731. a_i64_extend16_s,
  732. a_i64_extend32_s:
  733. ;
  734. { instructions with an integer const operand }
  735. a_i32_const,
  736. a_i64_const:
  737. begin
  738. if actasmtoken=AS_INTNUM then
  739. begin
  740. result.operands[1].opr.typ:=OPR_CONSTANT;
  741. result.operands[1].opr.val:=actinttoken;
  742. Consume(AS_INTNUM);
  743. end
  744. else
  745. begin
  746. { error: expected integer }
  747. result.Free;
  748. result:=nil;
  749. Consume(AS_INTNUM);
  750. end;
  751. end;
  752. { instructions with a float const operand }
  753. a_f32_const,
  754. a_f64_const:
  755. begin
  756. case actasmtoken of
  757. AS_INTNUM:
  758. begin
  759. result.operands[1].opr.typ:=OPR_FLOATCONSTANT;
  760. result.operands[1].opr.floatval:=actinttoken;
  761. Consume(AS_INTNUM);
  762. end;
  763. AS_REALNUM:
  764. begin
  765. result.operands[1].opr.typ:=OPR_FLOATCONSTANT;
  766. result.operands[1].opr.floatval:=actfloattoken;
  767. Consume(AS_REALNUM);
  768. end;
  769. else
  770. begin
  771. { error: expected real }
  772. result.Free;
  773. result:=nil;
  774. Consume(AS_REALNUM);
  775. end;
  776. end;
  777. end;
  778. { instructions with an optional memarg operand }
  779. a_i32_load,
  780. a_i64_load,
  781. a_f32_load,
  782. a_f64_load,
  783. a_i32_load8_s,
  784. a_i32_load8_u,
  785. a_i32_load16_s,
  786. a_i32_load16_u,
  787. a_i64_load8_s,
  788. a_i64_load8_u,
  789. a_i64_load16_s,
  790. a_i64_load16_u,
  791. a_i64_load32_s,
  792. a_i64_load32_u,
  793. a_i32_store,
  794. a_i64_store,
  795. a_f32_store,
  796. a_f64_store,
  797. a_i32_store8,
  798. a_i32_store16,
  799. a_i64_store8,
  800. a_i64_store16,
  801. a_i64_store32:
  802. begin
  803. { TODO: parse the optional memarg operand }
  804. result.operands[1].opr.typ:=OPR_CONSTANT;
  805. result.operands[1].opr.val:=0;
  806. end;
  807. else
  808. internalerror(2024071401);
  809. end;
  810. end;
  811. else
  812. {error};
  813. end;
  814. end;
  815. function twasmreader.Assemble: tlinkedlist;
  816. begin
  817. Message1(asmr_d_start_reading,'WebAssembly');
  818. firsttoken:=TRUE;
  819. { sets up all opcode and register tables in uppercase }
  820. if not _asmsorted then
  821. begin
  822. SetupTables;
  823. _asmsorted:=TRUE;
  824. end;
  825. curlist:=TAsmList.Create;
  826. { we might need to know which parameters are passed in registers }
  827. if not parse_generic then
  828. current_procinfo.generate_parameter_info;
  829. { start tokenizer }
  830. gettoken;
  831. { main loop }
  832. repeat
  833. Writeln(actasmtoken);
  834. case actasmtoken of
  835. AS_END:
  836. break; { end assembly block }
  837. else
  838. begin
  839. Consume(actasmtoken);
  840. //Message(asmr_e_syntax_error);
  841. //RecoverConsume(false);
  842. end;
  843. end;
  844. until false;
  845. { Return the list in an asmnode }
  846. assemble:=curlist;
  847. Message1(asmr_d_finish_reading,'WebAssembly');
  848. end;
  849. {*****************************************************************************
  850. Initialize
  851. *****************************************************************************}
  852. const
  853. asmmode_wasm_standard_info : tasmmodeinfo =
  854. (
  855. id : asmmode_standard;
  856. idtxt : 'STANDARD';
  857. casmreader : twasmreader;
  858. );
  859. initialization
  860. RegisterAsmMode(asmmode_wasm_standard_info);
  861. end.