cg386inl.pas 48 KB

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