cg386inl.pas 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089
  1. {
  2. $Id$
  3. Copyright (c) 1993-98 by Florian Klaempfl
  4. Generate i386 inline nodes
  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 cg386inl;
  19. interface
  20. uses
  21. tree;
  22. procedure secondinline(var p : ptree);
  23. implementation
  24. uses
  25. cobjects,verbose,globals,systems,files,
  26. symtable,aasm,types,
  27. hcodegen,temp_gen,pass_2,
  28. i386,cgai386,tgeni386,cg386ld,cg386cal;
  29. {*****************************************************************************
  30. Helpers
  31. *****************************************************************************}
  32. { reverts the parameter list }
  33. var nb_para : integer;
  34. function reversparameter(p : ptree) : ptree;
  35. var
  36. hp1,hp2 : ptree;
  37. begin
  38. hp1:=nil;
  39. nb_para := 0;
  40. while assigned(p) do
  41. begin
  42. { pull out }
  43. hp2:=p;
  44. p:=p^.right;
  45. inc(nb_para);
  46. { pull in }
  47. hp2^.right:=hp1;
  48. hp1:=hp2;
  49. end;
  50. reversparameter:=hp1;
  51. end;
  52. {*****************************************************************************
  53. SecondInLine
  54. *****************************************************************************}
  55. procedure secondinline(var p : ptree);
  56. const
  57. { tfloattype = (f32bit,s32real,s64real,s80real,s64bit); }
  58. float_name: array[tfloattype] of string[8]=
  59. ('FIXED','SINGLE','REAL','EXTENDED','COMP','FIXED16');
  60. incdecop:array[in_inc_x..in_dec_x] of tasmop=(A_INC,A_DEC);
  61. addsubop:array[in_inc_x..in_dec_x] of tasmop=(A_ADD,A_SUB);
  62. var
  63. aktfile : treference;
  64. ft : tfiletype;
  65. opsize : topsize;
  66. asmop : tasmop;
  67. pushed : tpushed;
  68. {inc/dec}
  69. addconstant : boolean;
  70. addvalue : longint;
  71. procedure handlereadwrite(doread,doln : boolean);
  72. { produces code for READ(LN) and WRITE(LN) }
  73. procedure loadstream;
  74. const
  75. io:array[0..1] of string[7]=('_OUTPUT','_INPUT');
  76. var
  77. r : preference;
  78. begin
  79. new(r);
  80. reset_reference(r^);
  81. r^.symbol:=stringdup('U_'+upper(target_info.system_unit)+io[byte(doread)]);
  82. concat_external(r^.symbol^,EXT_NEAR);
  83. exprasmlist^.concat(new(pai386,op_ref_reg(A_LEA,S_L,r,R_EDI)))
  84. end;
  85. var
  86. node,hp : ptree;
  87. typedtyp,
  88. pararesult : pdef;
  89. has_length : boolean;
  90. dummycoll : tdefcoll;
  91. iolabel : plabel;
  92. npara : longint;
  93. begin
  94. { I/O check }
  95. if cs_check_io in aktlocalswitches then
  96. begin
  97. getlabel(iolabel);
  98. emitl(A_LABEL,iolabel);
  99. end
  100. else
  101. iolabel:=nil;
  102. { for write of real with the length specified }
  103. has_length:=false;
  104. hp:=nil;
  105. { reserve temporary pointer to data variable }
  106. aktfile.symbol:=nil;
  107. gettempofsizereference(4,aktfile);
  108. { first state text data }
  109. ft:=ft_text;
  110. { and state a parameter ? }
  111. if p^.left=nil then
  112. begin
  113. { the following instructions are for "writeln;" }
  114. loadstream;
  115. { save @aktfile in temporary variable }
  116. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,S_L,R_EDI,newreference(aktfile))));
  117. end
  118. else
  119. begin
  120. { revers paramters }
  121. node:=reversparameter(p^.left);
  122. p^.left := node;
  123. npara := nb_para;
  124. { calculate data variable }
  125. { is first parameter a file type ? }
  126. if node^.left^.resulttype^.deftype=filedef then
  127. begin
  128. ft:=pfiledef(node^.left^.resulttype)^.filetype;
  129. if ft=ft_typed then
  130. typedtyp:=pfiledef(node^.left^.resulttype)^.typed_as;
  131. secondpass(node^.left);
  132. if codegenerror then
  133. exit;
  134. { save reference in temporary variables }
  135. if node^.left^.location.loc<>LOC_REFERENCE then
  136. begin
  137. CGMessage(cg_e_illegal_expression);
  138. exit;
  139. end;
  140. exprasmlist^.concat(new(pai386,op_ref_reg(A_LEA,S_L,newreference(node^.left^.location.reference),R_EDI)));
  141. { skip to the next parameter }
  142. node:=node^.right;
  143. end
  144. else
  145. begin
  146. { load stdin/stdout stream }
  147. loadstream;
  148. end;
  149. { save @aktfile in temporary variable }
  150. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,S_L,R_EDI,newreference(aktfile))));
  151. if doread then
  152. { parameter by READ gives call by reference }
  153. dummycoll.paratyp:=vs_var
  154. { an WRITE Call by "Const" }
  155. else
  156. dummycoll.paratyp:=vs_const;
  157. { because of secondcallparan, which otherwise attaches }
  158. if ft=ft_typed then
  159. { this is to avoid copy of simple const parameters }
  160. dummycoll.data:=new(pformaldef,init)
  161. else
  162. { I think, this isn't a good solution (FK) }
  163. dummycoll.data:=nil;
  164. while assigned(node) do
  165. begin
  166. pushusedregisters(pushed,$ff);
  167. hp:=node;
  168. node:=node^.right;
  169. hp^.right:=nil;
  170. if hp^.is_colon_para then
  171. CGMessage(parser_e_illegal_colon_qualifier);
  172. if ft=ft_typed then
  173. never_copy_const_param:=true;
  174. secondcallparan(hp,@dummycoll,false,false,0);
  175. if ft=ft_typed then
  176. never_copy_const_param:=false;
  177. hp^.right:=node;
  178. if codegenerror then
  179. exit;
  180. emit_push_mem(aktfile);
  181. if (ft=ft_typed) then
  182. begin
  183. { OK let's try this }
  184. { first we must only allow the right type }
  185. { we have to call blockread or blockwrite }
  186. { but the real problem is that }
  187. { reset and rewrite should have set }
  188. { the type size }
  189. { as recordsize for that file !!!! }
  190. { how can we make that }
  191. { I think that is only possible by adding }
  192. { reset and rewrite to the inline list a call }
  193. { allways read only one record by element }
  194. push_int(typedtyp^.size);
  195. if doread then
  196. emitcall('FPC_TYPED_READ',true)
  197. else
  198. emitcall('FPC_TYPED_WRITE',true);
  199. end
  200. else
  201. begin
  202. { save current position }
  203. pararesult:=hp^.left^.resulttype;
  204. { handle possible field width }
  205. { of course only for write(ln) }
  206. if not doread then
  207. begin
  208. { handle total width parameter }
  209. if assigned(node) and node^.is_colon_para then
  210. begin
  211. hp:=node;
  212. node:=node^.right;
  213. hp^.right:=nil;
  214. secondcallparan(hp,@dummycoll,false,false,0);
  215. hp^.right:=node;
  216. if codegenerror then
  217. exit;
  218. has_length:=true;
  219. end
  220. else
  221. if pararesult^.deftype<>floatdef then
  222. push_int(0)
  223. else
  224. push_int(-32767);
  225. { a second colon para for a float ? }
  226. if assigned(node) and node^.is_colon_para then
  227. begin
  228. hp:=node;
  229. node:=node^.right;
  230. hp^.right:=nil;
  231. secondcallparan(hp,@dummycoll,false,false,0);
  232. hp^.right:=node;
  233. if pararesult^.deftype<>floatdef then
  234. CGMessage(parser_e_illegal_colon_qualifier);
  235. if codegenerror then
  236. exit;
  237. end
  238. else
  239. begin
  240. if pararesult^.deftype=floatdef then
  241. push_int(-1);
  242. end
  243. end;
  244. case pararesult^.deftype of
  245. stringdef : begin
  246. if doread then
  247. begin
  248. { push maximum string length }
  249. push_int(pstringdef(pararesult)^.len);
  250. case pstringdef(pararesult)^.string_typ of
  251. st_shortstring:
  252. emitcall ('FPC_READ_TEXT_STRING',true);
  253. st_ansistring:
  254. emitcall ('FPC_READ_TEXT_ANSISTRING',true);
  255. st_longstring:
  256. emitcall ('FPC_READ_TEXT_LONGSTRING',true);
  257. st_widestring:
  258. emitcall ('FPC_READ_TEXT_ANSISTRING',true);
  259. end
  260. end
  261. else
  262. Case pstringdef(Pararesult)^.string_typ of
  263. st_shortstring:
  264. emitcall ('FPC_WRITE_TEXT_STRING',true);
  265. st_ansistring:
  266. emitcall ('FPC_WRITE_TEXT_ANSISTRING',true);
  267. st_longstring:
  268. emitcall ('FPC_WRITE_TEXT_LONGSTRING',true);
  269. st_widestring:
  270. emitcall ('FPC_WRITE_TEXT_ANSISTRING',true);
  271. end;
  272. end;
  273. pointerdef : begin
  274. if is_equal(ppointerdef(pararesult)^.definition,cchardef) then
  275. begin
  276. if doread then
  277. emitcall('FPC_READ_TEXT_PCHAR_AS_POINTER',true)
  278. else
  279. emitcall('FPC_WRITE_TEXT_PCHAR_AS_POINTER',true);
  280. end;
  281. end;
  282. arraydef : begin
  283. if is_chararray(pararesult) then
  284. begin
  285. if doread then
  286. emitcall('FPC_READ_TEXT_PCHAR_AS_ARRAY',true)
  287. else
  288. emitcall('FPC_WRITE_TEXT_PCHAR_AS_ARRAY',true);
  289. end;
  290. end;
  291. floatdef : begin
  292. if doread then
  293. emitcall('FPC_READ_TEXT_'+float_name[pfloatdef(pararesult)^.typ],true)
  294. else
  295. emitcall('FPC_WRITE_TEXT_'+float_name[pfloatdef(pararesult)^.typ],true);
  296. end;
  297. orddef : begin
  298. case porddef(pararesult)^.typ of
  299. u8bit : if doread then
  300. emitcall('FPC_READ_TEXT_BYTE',true);
  301. s8bit : if doread then
  302. emitcall('FPC_READ_TEXT_SHORTINT',true);
  303. u16bit : if doread then
  304. emitcall('FPC_READ_TEXT_WORD',true);
  305. s16bit : if doread then
  306. emitcall('FPC_READ_TEXT_INTEGER',true);
  307. s32bit : if doread then
  308. emitcall('FPC_READ_TEXT_LONGINT',true)
  309. else
  310. emitcall('FPC_WRITE_TEXT_LONGINT',true);
  311. u32bit : if doread then
  312. emitcall('FPC_READ_TEXT_CARDINAL',true)
  313. else
  314. emitcall('FPC_WRITE_TEXT_CARDINAL',true);
  315. uchar : if doread then
  316. emitcall('FPC_READ_TEXT_CHAR',true)
  317. else
  318. emitcall('FPC_WRITE_TEXT_CHAR',true);
  319. bool8bit,
  320. bool16bit,
  321. bool32bit : if doread then
  322. CGMessage(parser_e_illegal_parameter_list)
  323. else
  324. emitcall('FPC_WRITE_TEXT_BOOLEAN',true);
  325. end;
  326. end;
  327. end;
  328. end;
  329. { load ESI in methods again }
  330. popusedregisters(pushed);
  331. maybe_loadesi;
  332. end;
  333. end;
  334. { Insert end of writing for textfiles }
  335. if ft=ft_text then
  336. begin
  337. pushusedregisters(pushed,$ff);
  338. emit_push_mem(aktfile);
  339. if doread then
  340. begin
  341. if doln then
  342. emitcall('FPC_READLN_END',true)
  343. else
  344. emitcall('FPC_READ_END',true);
  345. end
  346. else
  347. begin
  348. if doln then
  349. emitcall('FPC_WRITELN_END',true)
  350. else
  351. emitcall('FPC_WRITE_END',true);
  352. end;
  353. popusedregisters(pushed);
  354. maybe_loadesi;
  355. end;
  356. { Insert IOCheck if set }
  357. if assigned(iolabel) then
  358. begin
  359. { registers are saved in the procedure }
  360. exprasmlist^.concat(new(pai386,op_csymbol(A_PUSH,S_L,newcsymbol(lab2str(iolabel),0))));
  361. emitcall('FPC_IOCHECK',true);
  362. end;
  363. { Freeup all used temps }
  364. ungetiftemp(aktfile);
  365. if assigned(p^.left) then
  366. begin
  367. p^.left:=reversparameter(p^.left);
  368. if npara<>nb_para then
  369. CGMessage(cg_f_internal_error_in_secondinline);
  370. hp:=p^.left;
  371. while assigned(hp) do
  372. begin
  373. if assigned(hp^.left) then
  374. if (hp^.left^.location.loc in [LOC_MEM,LOC_REFERENCE]) then
  375. ungetiftemp(hp^.left^.location.reference);
  376. hp:=hp^.right;
  377. end;
  378. end;
  379. end;
  380. procedure handle_str;
  381. var
  382. hp,node : ptree;
  383. dummycoll : tdefcoll;
  384. is_real,has_length : boolean;
  385. begin
  386. pushusedregisters(pushed,$ff);
  387. node:=p^.left;
  388. is_real:=false;
  389. has_length:=false;
  390. while assigned(node^.right) do node:=node^.right;
  391. { if a real parameter somewhere then call REALSTR }
  392. if (node^.left^.resulttype^.deftype=floatdef) then
  393. is_real:=true;
  394. node:=p^.left;
  395. { we have at least two args }
  396. { with at max 2 colon_para in between }
  397. { first arg longint or float }
  398. hp:=node;
  399. node:=node^.right;
  400. hp^.right:=nil;
  401. dummycoll.data:=hp^.resulttype;
  402. { string arg }
  403. dummycoll.paratyp:=vs_var;
  404. secondcallparan(hp,@dummycoll,false
  405. ,false,0
  406. );
  407. if codegenerror then
  408. exit;
  409. dummycoll.paratyp:=vs_const;
  410. disposetree(p^.left);
  411. p^.left:=nil;
  412. { second arg }
  413. hp:=node;
  414. node:=node^.right;
  415. hp^.right:=nil;
  416. { frac para }
  417. if hp^.is_colon_para and assigned(node) and
  418. node^.is_colon_para then
  419. begin
  420. dummycoll.data:=hp^.resulttype;
  421. secondcallparan(hp,@dummycoll,false
  422. ,false,0
  423. );
  424. if codegenerror then
  425. exit;
  426. disposetree(hp);
  427. hp:=node;
  428. node:=node^.right;
  429. hp^.right:=nil;
  430. has_length:=true;
  431. end
  432. else
  433. if is_real then
  434. push_int(-1);
  435. { third arg, length only if is_real }
  436. if hp^.is_colon_para then
  437. begin
  438. dummycoll.data:=hp^.resulttype;
  439. secondcallparan(hp,@dummycoll,false
  440. ,false,0
  441. );
  442. if codegenerror then
  443. exit;
  444. disposetree(hp);
  445. hp:=node;
  446. node:=node^.right;
  447. hp^.right:=nil;
  448. end
  449. else
  450. if is_real then
  451. push_int(-32767)
  452. else
  453. push_int(-1);
  454. { last arg longint or real }
  455. secondcallparan(hp,@dummycoll,false
  456. ,false,0
  457. );
  458. disposetree(hp);
  459. if codegenerror then
  460. exit;
  461. if is_real then
  462. emitcall('FPC_STR_'+float_name[pfloatdef(hp^.resulttype)^.typ],true)
  463. else if porddef(hp^.resulttype)^.typ=u32bit then
  464. emitcall('FPC_STR_CARDINAL',true)
  465. else
  466. emitcall('FPC_STR_LONGINT',true);
  467. popusedregisters(pushed);
  468. end;
  469. var
  470. r : preference;
  471. hp : ptree;
  472. l : longint;
  473. ispushed : boolean;
  474. hregister : tregister;
  475. otlabel,oflabel : plabel;
  476. oldpushedparasize : longint;
  477. begin
  478. { save & reset pushedparasize }
  479. oldpushedparasize:=pushedparasize;
  480. pushedparasize:=0;
  481. case p^.inlinenumber of
  482. in_assert_x_y:
  483. begin
  484. otlabel:=truelabel;
  485. oflabel:=falselabel;
  486. getlabel(truelabel);
  487. getlabel(falselabel);
  488. secondpass(p^.left^.left);
  489. if cs_do_assertion in aktlocalswitches then
  490. begin
  491. maketojumpbool(p^.left^.left);
  492. emitl(A_LABEL,falselabel);
  493. { erroraddr }
  494. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,R_EBP)));
  495. { lineno }
  496. exprasmlist^.concat(new(pai386,op_const(A_PUSH,S_L,aktfilepos.line)));
  497. { filename string }
  498. hp:=genstringconstnode(current_module^.sourcefiles^.get_file_name(aktfilepos.fileindex));
  499. secondpass(hp);
  500. if codegenerror then
  501. exit;
  502. emitpushreferenceaddr(exprasmlist,hp^.location.reference);
  503. disposetree(hp);
  504. { push msg }
  505. secondpass(p^.left^.right^.left);
  506. emitpushreferenceaddr(exprasmlist,p^.left^.right^.left^.location.reference);
  507. { call }
  508. emitcall('FPC_ASSERT',true);
  509. emitl(A_LABEL,truelabel);
  510. end;
  511. freelabel(truelabel);
  512. freelabel(falselabel);
  513. truelabel:=otlabel;
  514. falselabel:=oflabel;
  515. end;
  516. in_lo_word,
  517. in_hi_word :
  518. begin
  519. secondpass(p^.left);
  520. p^.location.loc:=LOC_REGISTER;
  521. if p^.left^.location.loc<>LOC_REGISTER then
  522. begin
  523. if p^.left^.location.loc=LOC_CREGISTER then
  524. begin
  525. p^.location.register:=reg32toreg16(getregister32);
  526. emit_reg_reg(A_MOV,S_W,p^.left^.location.register,
  527. p^.location.register);
  528. end
  529. else
  530. begin
  531. del_reference(p^.left^.location.reference);
  532. p^.location.register:=reg32toreg16(getregister32);
  533. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_W,newreference(p^.left^.location.reference),
  534. p^.location.register)));
  535. end;
  536. end
  537. else p^.location.register:=p^.left^.location.register;
  538. if p^.inlinenumber=in_hi_word then
  539. exprasmlist^.concat(new(pai386,op_const_reg(A_SHR,S_W,8,p^.location.register)));
  540. p^.location.register:=reg16toreg8(p^.location.register);
  541. end;
  542. in_high_x :
  543. begin
  544. if is_open_array(p^.left^.resulttype) then
  545. begin
  546. secondpass(p^.left);
  547. del_reference(p^.left^.location.reference);
  548. p^.location.register:=getregister32;
  549. new(r);
  550. reset_reference(r^);
  551. r^.base:=highframepointer;
  552. r^.offset:=highoffset+4;
  553. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,
  554. r,p^.location.register)));
  555. end
  556. end;
  557. in_sizeof_x,
  558. in_typeof_x :
  559. begin
  560. { sizeof(openarray) handling }
  561. if (p^.inlinenumber=in_sizeof_x) and
  562. is_open_array(p^.left^.resulttype) then
  563. begin
  564. { sizeof(openarray)=high(openarray)+1 }
  565. secondpass(p^.left);
  566. del_reference(p^.left^.location.reference);
  567. p^.location.register:=getregister32;
  568. new(r);
  569. reset_reference(r^);
  570. r^.base:=highframepointer;
  571. r^.offset:=highoffset+4;
  572. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,
  573. r,p^.location.register)));
  574. exprasmlist^.concat(new(pai386,op_reg(A_INC,S_L,
  575. p^.location.register)));
  576. if parraydef(p^.left^.resulttype)^.elesize<>1 then
  577. exprasmlist^.concat(new(pai386,op_const_reg(A_IMUL,S_L,
  578. parraydef(p^.left^.resulttype)^.elesize,p^.location.register)));
  579. end
  580. else
  581. begin
  582. { for both cases load vmt }
  583. if p^.left^.treetype=typen then
  584. begin
  585. p^.location.register:=getregister32;
  586. exprasmlist^.concat(new(pai386,op_csymbol_reg(A_MOV,
  587. S_L,newcsymbol(pobjectdef(p^.left^.resulttype)^.vmt_mangledname,0),
  588. p^.location.register)));
  589. end
  590. else
  591. begin
  592. secondpass(p^.left);
  593. del_reference(p^.left^.location.reference);
  594. p^.location.loc:=LOC_REGISTER;
  595. p^.location.register:=getregister32;
  596. { load VMT pointer }
  597. inc(p^.left^.location.reference.offset,
  598. pobjectdef(p^.left^.resulttype)^.vmt_offset);
  599. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,
  600. newreference(p^.left^.location.reference),
  601. p^.location.register)));
  602. end;
  603. { in sizeof load size }
  604. if p^.inlinenumber=in_sizeof_x then
  605. begin
  606. new(r);
  607. reset_reference(r^);
  608. r^.base:=p^.location.register;
  609. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,r,
  610. p^.location.register)));
  611. end;
  612. end;
  613. end;
  614. in_lo_long,
  615. in_hi_long :
  616. begin
  617. secondpass(p^.left);
  618. p^.location.loc:=LOC_REGISTER;
  619. if p^.left^.location.loc<>LOC_REGISTER then
  620. begin
  621. if p^.left^.location.loc=LOC_CREGISTER then
  622. begin
  623. p^.location.register:=getregister32;
  624. emit_reg_reg(A_MOV,S_L,p^.left^.location.register,
  625. p^.location.register);
  626. end
  627. else
  628. begin
  629. del_reference(p^.left^.location.reference);
  630. p^.location.register:=getregister32;
  631. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,newreference(p^.left^.location.reference),
  632. p^.location.register)));
  633. end;
  634. end
  635. else p^.location.register:=p^.left^.location.register;
  636. if p^.inlinenumber=in_hi_long then
  637. exprasmlist^.concat(new(pai386,op_const_reg(A_SHR,S_L,16,p^.location.register)));
  638. p^.location.register:=reg32toreg16(p^.location.register);
  639. end;
  640. in_length_string :
  641. begin
  642. secondpass(p^.left);
  643. set_location(p^.location,p^.left^.location);
  644. { length in ansi strings is at offset -8 }
  645. {$ifdef UseAnsiString}
  646. if is_ansistring(p^.left^.resulttype) then
  647. dec(p^.location.reference.offset,8);
  648. {$endif UseAnsiString}
  649. end;
  650. in_pred_x,
  651. in_succ_x:
  652. begin
  653. secondpass(p^.left);
  654. if p^.inlinenumber=in_pred_x then
  655. asmop:=A_DEC
  656. else
  657. asmop:=A_INC;
  658. case p^.resulttype^.size of
  659. 4 : opsize:=S_L;
  660. 2 : opsize:=S_W;
  661. 1 : opsize:=S_B;
  662. else
  663. internalerror(10080);
  664. end;
  665. p^.location.loc:=LOC_REGISTER;
  666. if p^.left^.location.loc<>LOC_REGISTER then
  667. begin
  668. p^.location.register:=getregister32;
  669. if (p^.resulttype^.size=2) then
  670. p^.location.register:=reg32toreg16(p^.location.register);
  671. if (p^.resulttype^.size=1) then
  672. p^.location.register:=reg32toreg8(p^.location.register);
  673. if p^.left^.location.loc=LOC_CREGISTER then
  674. emit_reg_reg(A_MOV,opsize,p^.left^.location.register,
  675. p^.location.register)
  676. else
  677. if p^.left^.location.loc=LOC_FLAGS then
  678. exprasmlist^.concat(new(pai386,op_reg(flag_2_set[p^.left^.location.resflags],S_B,
  679. p^.location.register)))
  680. else
  681. begin
  682. del_reference(p^.left^.location.reference);
  683. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,opsize,newreference(p^.left^.location.reference),
  684. p^.location.register)));
  685. end;
  686. end
  687. else p^.location.register:=p^.left^.location.register;
  688. exprasmlist^.concat(new(pai386,op_reg(asmop,opsize,
  689. p^.location.register)));
  690. emitoverflowcheck(p);
  691. emitrangecheck(p);
  692. end;
  693. in_dec_x,
  694. in_inc_x :
  695. begin
  696. { set defaults }
  697. addvalue:=1;
  698. addconstant:=true;
  699. { load first parameter, must be a reference }
  700. secondpass(p^.left^.left);
  701. case p^.left^.left^.resulttype^.deftype of
  702. orddef,
  703. enumdef : begin
  704. case p^.left^.left^.resulttype^.size of
  705. 1 : opsize:=S_B;
  706. 2 : opsize:=S_W;
  707. 4 : opsize:=S_L;
  708. end;
  709. end;
  710. pointerdef : begin
  711. opsize:=S_L;
  712. if porddef(ppointerdef(p^.left^.left^.resulttype)^.definition)=voiddef then
  713. addvalue:=1
  714. else
  715. addvalue:=ppointerdef(p^.left^.left^.resulttype)^.definition^.savesize;
  716. end;
  717. else
  718. internalerror(10081);
  719. end;
  720. { second argument specified?, must be a s32bit in register }
  721. if assigned(p^.left^.right) then
  722. begin
  723. secondpass(p^.left^.right^.left);
  724. { when constant, just multiply the addvalue }
  725. if is_constintnode(p^.left^.right^.left) then
  726. addvalue:=addvalue*get_ordinal_value(p^.left^.right^.left)
  727. else
  728. begin
  729. case p^.left^.right^.left^.location.loc of
  730. LOC_REGISTER,
  731. LOC_CREGISTER : hregister:=p^.left^.right^.left^.location.register;
  732. LOC_MEM,
  733. LOC_REFERENCE : begin
  734. del_reference(p^.left^.right^.left^.location.reference);
  735. hregister:=getregister32;
  736. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,
  737. newreference(p^.left^.right^.left^.location.reference),hregister)));
  738. end;
  739. else
  740. internalerror(10082);
  741. end;
  742. { insert multiply with addvalue if its >1 }
  743. if addvalue>1 then
  744. exprasmlist^.concat(new(pai386,op_const_reg(A_IMUL,opsize,
  745. addvalue,hregister)));
  746. addconstant:=false;
  747. end;
  748. end;
  749. { write the add instruction }
  750. if addconstant then
  751. begin
  752. if (addvalue=1) and not(cs_check_overflow in aktlocalswitches) then
  753. begin
  754. if p^.left^.left^.location.loc=LOC_CREGISTER then
  755. exprasmlist^.concat(new(pai386,op_reg(incdecop[p^.inlinenumber],opsize,
  756. p^.left^.left^.location.register)))
  757. else
  758. exprasmlist^.concat(new(pai386,op_ref(incdecop[p^.inlinenumber],opsize,
  759. newreference(p^.left^.left^.location.reference))))
  760. end
  761. else
  762. begin
  763. if p^.left^.left^.location.loc=LOC_CREGISTER then
  764. exprasmlist^.concat(new(pai386,op_const_reg(addsubop[p^.inlinenumber],opsize,
  765. addvalue,p^.left^.left^.location.register)))
  766. else
  767. exprasmlist^.concat(new(pai386,op_const_ref(addsubop[p^.inlinenumber],opsize,
  768. addvalue,newreference(p^.left^.left^.location.reference))));
  769. end
  770. end
  771. else
  772. begin
  773. if p^.left^.left^.location.loc=LOC_CREGISTER then
  774. exprasmlist^.concat(new(pai386,op_reg_reg(addsubop[p^.inlinenumber],opsize,
  775. hregister,p^.left^.left^.location.register)))
  776. else
  777. exprasmlist^.concat(new(pai386,op_reg_ref(addsubop[p^.inlinenumber],opsize,
  778. hregister,newreference(p^.left^.left^.location.reference))));
  779. ungetregister32(hregister);
  780. end;
  781. emitoverflowcheck(p^.left^.left);
  782. emitrangecheck(p^.left^.left);
  783. end;
  784. in_assigned_x :
  785. begin
  786. secondpass(p^.left^.left);
  787. p^.location.loc:=LOC_FLAGS;
  788. if (p^.left^.left^.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
  789. begin
  790. exprasmlist^.concat(new(pai386,op_reg_reg(A_OR,S_L,
  791. p^.left^.left^.location.register,
  792. p^.left^.left^.location.register)));
  793. ungetregister32(p^.left^.left^.location.register);
  794. end
  795. else
  796. begin
  797. exprasmlist^.concat(new(pai386,op_const_ref(A_CMP,S_L,0,
  798. newreference(p^.left^.left^.location.reference))));
  799. del_reference(p^.left^.left^.location.reference);
  800. end;
  801. p^.location.resflags:=F_NE;
  802. end;
  803. in_reset_typedfile,in_rewrite_typedfile :
  804. begin
  805. pushusedregisters(pushed,$ff);
  806. exprasmlist^.concat(new(pai386,op_const(A_PUSH,S_L,pfiledef(p^.left^.resulttype)^.typed_as^.size)));
  807. secondload(p^.left);
  808. emitpushreferenceaddr(exprasmlist,p^.left^.location.reference);
  809. if p^.inlinenumber=in_reset_typedfile then
  810. emitcall('FPC_RESET_TYPED',true)
  811. else
  812. emitcall('FPC_REWRITE_TYPED',true);
  813. popusedregisters(pushed);
  814. end;
  815. in_write_x :
  816. handlereadwrite(false,false);
  817. in_writeln_x :
  818. handlereadwrite(false,true);
  819. in_read_x :
  820. handlereadwrite(true,false);
  821. in_readln_x :
  822. handlereadwrite(true,true);
  823. in_str_x_string :
  824. begin
  825. handle_str;
  826. maybe_loadesi;
  827. end;
  828. in_include_x_y,
  829. in_exclude_x_y:
  830. begin
  831. secondpass(p^.left^.left);
  832. if p^.left^.right^.left^.treetype=ordconstn then
  833. begin
  834. { calculate bit position }
  835. l:=1 shl (p^.left^.right^.left^.value mod 32);
  836. { determine operator }
  837. if p^.inlinenumber=in_include_x_y then
  838. asmop:=A_OR
  839. else
  840. begin
  841. asmop:=A_AND;
  842. l:=not(l);
  843. end;
  844. if (p^.left^.left^.location.loc=LOC_REFERENCE) then
  845. begin
  846. inc(p^.left^.left^.location.reference.offset,(p^.left^.right^.left^.value div 32)*4);
  847. exprasmlist^.concat(new(pai386,op_const_ref(asmop,S_L,
  848. l,newreference(p^.left^.left^.location.reference))));
  849. del_reference(p^.left^.left^.location.reference);
  850. end
  851. else
  852. { LOC_CREGISTER }
  853. exprasmlist^.concat(new(pai386,op_const_reg(asmop,S_L,
  854. l,p^.left^.left^.location.register)));
  855. end
  856. else
  857. begin
  858. { generate code for the element to set }
  859. ispushed:=maybe_push(p^.left^.right^.left^.registers32,p^.left^.left);
  860. secondpass(p^.left^.right^.left);
  861. if ispushed then
  862. restore(p^.left^.left);
  863. { determine asm operator }
  864. if p^.inlinenumber=in_include_x_y then
  865. asmop:=A_BTS
  866. else
  867. asmop:=A_BTR;
  868. if psetdef(p^.left^.resulttype)^.settype=smallset then
  869. begin
  870. if p^.left^.right^.left^.location.loc in [LOC_CREGISTER,LOC_REGISTER] then
  871. hregister:=p^.left^.right^.left^.location.register
  872. else
  873. begin
  874. hregister:=R_EDI;
  875. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,
  876. newreference(p^.left^.right^.left^.location.reference),R_EDI)));
  877. end;
  878. if (p^.left^.left^.location.loc=LOC_REFERENCE) then
  879. exprasmlist^.concat(new(pai386,op_reg_ref(asmop,S_L,R_EDI,
  880. newreference(p^.left^.right^.left^.location.reference))))
  881. else
  882. exprasmlist^.concat(new(pai386,op_reg_reg(asmop,S_L,R_EDI,
  883. p^.left^.right^.left^.location.register)));
  884. end
  885. else
  886. begin
  887. end;
  888. end;
  889. end;
  890. else internalerror(9);
  891. end;
  892. { reset pushedparasize }
  893. pushedparasize:=oldpushedparasize;
  894. end;
  895. end.
  896. {
  897. $Log$
  898. Revision 1.13 1998-10-13 16:50:02 pierre
  899. * undid some changes of Peter that made the compiler wrong
  900. for m68k (I had to reinsert some ifdefs)
  901. * removed several memory leaks under m68k
  902. * removed the meory leaks for assembler readers
  903. * cross compiling shoud work again better
  904. ( crosscompiling sysamiga works
  905. but as68k still complain about some code !)
  906. Revision 1.12 1998/10/08 17:17:12 pierre
  907. * current_module old scanner tagged as invalid if unit is recompiled
  908. + added ppheap for better info on tracegetmem of heaptrc
  909. (adds line column and file index)
  910. * several memory leaks removed ith help of heaptrc !!
  911. Revision 1.11 1998/10/05 21:33:15 peter
  912. * fixed 161,165,166,167,168
  913. Revision 1.10 1998/10/05 12:32:44 peter
  914. + assert() support
  915. Revision 1.8 1998/10/02 10:35:09 peter
  916. * support for inc(pointer,value) which now increases with value instead
  917. of 0*value :)
  918. Revision 1.7 1998/09/21 08:45:07 pierre
  919. + added vmt_offset in tobjectdef.write for fututre use
  920. (first steps to have objects without vmt if no virtual !!)
  921. + added fpu_used field for tabstractprocdef :
  922. sets this level to 2 if the functions return with value in FPU
  923. (is then set to correct value at parsing of implementation)
  924. THIS MIGHT refuse some code with FPU expression too complex
  925. that were accepted before and even in some cases
  926. that don't overflow in fact
  927. ( like if f : float; is a forward that finally in implementation
  928. only uses one fpu register !!)
  929. Nevertheless I think that it will improve security on
  930. FPU operations !!
  931. * most other changes only for UseBrowser code
  932. (added symtable references for record and objects)
  933. local switch for refs to args and local of each function
  934. (static symtable still missing)
  935. UseBrowser still not stable and probably broken by
  936. the definition hash array !!
  937. Revision 1.6 1998/09/20 12:26:37 peter
  938. * merged fixes
  939. Revision 1.5 1998/09/17 09:42:15 peter
  940. + pass_2 for cg386
  941. * Message() -> CGMessage() for pass_1/pass_2
  942. Revision 1.4 1998/09/14 10:43:49 peter
  943. * all internal RTL functions start with FPC_
  944. Revision 1.3.2.1 1998/09/20 12:20:07 peter
  945. * Fixed stack not on 4 byte boundary when doing a call
  946. Revision 1.3 1998/09/05 23:03:57 florian
  947. * some fixes to get -Or work:
  948. - inc/dec didn't take care of CREGISTER
  949. - register calculcation of inc/dec was wrong
  950. - var/const parameters get now assigned 32 bit register, but
  951. const parameters only if they are passed by reference !
  952. Revision 1.2 1998/09/04 08:41:40 peter
  953. * updated some error CGMessages
  954. Revision 1.1 1998/08/31 12:22:14 peter
  955. * secondinline moved to cg386inl
  956. Revision 1.19 1998/08/31 08:52:03 peter
  957. * fixed error 10 with succ() and pref()
  958. Revision 1.18 1998/08/20 21:36:38 peter
  959. * fixed 'with object do' bug
  960. Revision 1.17 1998/08/19 16:07:36 jonas
  961. * changed optimizer switches + cleanup of DestroyRefs in daopt386.pas
  962. Revision 1.16 1998/08/18 09:24:36 pierre
  963. * small warning position bug fixed
  964. * support_mmx switches splitting was missing
  965. * rhide error and warning output corrected
  966. Revision 1.15 1998/08/13 11:00:09 peter
  967. * fixed procedure<>procedure construct
  968. Revision 1.14 1998/08/11 14:05:33 peter
  969. * fixed sizeof(array of char)
  970. Revision 1.13 1998/08/10 14:49:45 peter
  971. + localswitches, moduleswitches, globalswitches splitting
  972. Revision 1.12 1998/07/30 13:30:31 florian
  973. * final implemenation of exception support, maybe it needs
  974. some fixes :)
  975. Revision 1.11 1998/07/24 22:16:52 florian
  976. * internal error 10 together with array access fixed. I hope
  977. that's the final fix.
  978. Revision 1.10 1998/07/18 22:54:23 florian
  979. * some ansi/wide/longstring support fixed:
  980. o parameter passing
  981. o returning as result from functions
  982. Revision 1.9 1998/07/07 17:40:37 peter
  983. * packrecords 4 works
  984. * word aligning of parameters
  985. Revision 1.8 1998/07/06 15:51:15 michael
  986. Added length checking for string reading
  987. Revision 1.7 1998/07/06 14:19:51 michael
  988. + Added calls for reading/writing ansistrings
  989. Revision 1.6 1998/07/01 15:28:48 peter
  990. + better writeln/readln handling, now 100% like tp7
  991. Revision 1.5 1998/06/25 14:04:17 peter
  992. + internal inc/dec
  993. Revision 1.4 1998/06/25 08:48:06 florian
  994. * first version of rtti support
  995. Revision 1.3 1998/06/09 16:01:33 pierre
  996. + added procedure directive parsing for procvars
  997. (accepted are popstack cdecl and pascal)
  998. + added C vars with the following syntax
  999. var C calias 'true_c_name';(can be followed by external)
  1000. reason is that you must add the Cprefix
  1001. which is target dependent
  1002. Revision 1.2 1998/06/08 13:13:29 pierre
  1003. + temporary variables now in temp_gen.pas unit
  1004. because it is processor independent
  1005. * mppc68k.bat modified to undefine i386 and support_mmx
  1006. (which are defaults for i386)
  1007. Revision 1.1 1998/06/05 17:44:10 peter
  1008. * splitted cgi386
  1009. }