cg386inl.pas 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074
  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 (parraydef(pararesult)^.lowrange=0) and
  284. is_equal(parraydef(pararesult)^.definition,cchardef) then
  285. begin
  286. if doread then
  287. emitcall('FPC_READ_TEXT_PCHAR_AS_ARRAY',true)
  288. else
  289. emitcall('FPC_WRITE_TEXT_PCHAR_AS_ARRAY',true);
  290. end;
  291. end;
  292. floatdef : begin
  293. if doread then
  294. emitcall('FPC_READ_TEXT_'+float_name[pfloatdef(pararesult)^.typ],true)
  295. else
  296. emitcall('FPC_WRITE_TEXT_'+float_name[pfloatdef(pararesult)^.typ],true);
  297. end;
  298. orddef : begin
  299. case porddef(pararesult)^.typ of
  300. u8bit : if doread then
  301. emitcall('FPC_READ_TEXT_BYTE',true);
  302. s8bit : if doread then
  303. emitcall('FPC_READ_TEXT_SHORTINT',true);
  304. u16bit : if doread then
  305. emitcall('FPC_READ_TEXT_WORD',true);
  306. s16bit : if doread then
  307. emitcall('FPC_READ_TEXT_INTEGER',true);
  308. s32bit : if doread then
  309. emitcall('FPC_READ_TEXT_LONGINT',true)
  310. else
  311. emitcall('FPC_WRITE_TEXT_LONGINT',true);
  312. u32bit : if doread then
  313. emitcall('FPC_READ_TEXT_CARDINAL',true)
  314. else
  315. emitcall('FPC_WRITE_TEXT_CARDINAL',true);
  316. uchar : if doread then
  317. emitcall('FPC_READ_TEXT_CHAR',true)
  318. else
  319. emitcall('FPC_WRITE_TEXT_CHAR',true);
  320. bool8bit,
  321. bool16bit,
  322. bool32bit : if doread then
  323. CGMessage(parser_e_illegal_parameter_list)
  324. else
  325. emitcall('FPC_WRITE_TEXT_BOOLEAN',true);
  326. end;
  327. end;
  328. end;
  329. end;
  330. { load ESI in methods again }
  331. popusedregisters(pushed);
  332. maybe_loadesi;
  333. end;
  334. end;
  335. { Insert end of writing for textfiles }
  336. if ft=ft_text then
  337. begin
  338. pushusedregisters(pushed,$ff);
  339. emit_push_mem(aktfile);
  340. if doread then
  341. begin
  342. if doln then
  343. emitcall('FPC_READLN_END',true)
  344. else
  345. emitcall('FPC_READ_END',true);
  346. end
  347. else
  348. begin
  349. if doln then
  350. emitcall('FPC_WRITELN_END',true)
  351. else
  352. emitcall('FPC_WRITE_END',true);
  353. end;
  354. popusedregisters(pushed);
  355. maybe_loadesi;
  356. end;
  357. { Insert IOCheck if set }
  358. if assigned(iolabel) then
  359. begin
  360. { registers are saved in the procedure }
  361. exprasmlist^.concat(new(pai386,op_csymbol(A_PUSH,S_L,newcsymbol(lab2str(iolabel),0))));
  362. emitcall('FPC_IOCHECK',true);
  363. end;
  364. { Freeup all used temps }
  365. ungetiftemp(aktfile);
  366. if assigned(p^.left) then
  367. begin
  368. p^.left:=reversparameter(p^.left);
  369. if npara<>nb_para then
  370. CGMessage(cg_f_internal_error_in_secondinline);
  371. hp:=p^.left;
  372. while assigned(hp) do
  373. begin
  374. if assigned(hp^.left) then
  375. if (hp^.left^.location.loc in [LOC_MEM,LOC_REFERENCE]) then
  376. ungetiftemp(hp^.left^.location.reference);
  377. hp:=hp^.right;
  378. end;
  379. end;
  380. end;
  381. procedure handle_str;
  382. var
  383. hp,node : ptree;
  384. dummycoll : tdefcoll;
  385. is_real,has_length : boolean;
  386. begin
  387. pushusedregisters(pushed,$ff);
  388. node:=p^.left;
  389. is_real:=false;
  390. has_length:=false;
  391. while assigned(node^.right) do node:=node^.right;
  392. { if a real parameter somewhere then call REALSTR }
  393. if (node^.left^.resulttype^.deftype=floatdef) then
  394. is_real:=true;
  395. node:=p^.left;
  396. { we have at least two args }
  397. { with at max 2 colon_para in between }
  398. { first arg longint or float }
  399. hp:=node;
  400. node:=node^.right;
  401. hp^.right:=nil;
  402. dummycoll.data:=hp^.resulttype;
  403. { string arg }
  404. dummycoll.paratyp:=vs_var;
  405. secondcallparan(hp,@dummycoll,false
  406. ,false,0
  407. );
  408. if codegenerror then
  409. exit;
  410. dummycoll.paratyp:=vs_const;
  411. { second arg }
  412. hp:=node;
  413. node:=node^.right;
  414. hp^.right:=nil;
  415. { frac para }
  416. if hp^.is_colon_para and assigned(node) and
  417. node^.is_colon_para then
  418. begin
  419. dummycoll.data:=hp^.resulttype;
  420. secondcallparan(hp,@dummycoll,false
  421. ,false,0
  422. );
  423. if codegenerror then
  424. exit;
  425. hp:=node;
  426. node:=node^.right;
  427. hp^.right:=nil;
  428. has_length:=true;
  429. end
  430. else
  431. if is_real then
  432. push_int(-1);
  433. { third arg, length only if is_real }
  434. if hp^.is_colon_para then
  435. begin
  436. dummycoll.data:=hp^.resulttype;
  437. secondcallparan(hp,@dummycoll,false
  438. ,false,0
  439. );
  440. if codegenerror then
  441. exit;
  442. hp:=node;
  443. node:=node^.right;
  444. hp^.right:=nil;
  445. end
  446. else
  447. if is_real then
  448. push_int(-32767)
  449. else
  450. push_int(-1);
  451. { last arg longint or real }
  452. secondcallparan(hp,@dummycoll,false
  453. ,false,0
  454. );
  455. if codegenerror then
  456. exit;
  457. if is_real then
  458. emitcall('FPC_STR_'+float_name[pfloatdef(hp^.resulttype)^.typ],true)
  459. else if porddef(hp^.resulttype)^.typ=u32bit then
  460. emitcall('FPC_STR_CARDINAL',true)
  461. else
  462. emitcall('FPC_STR_LONGINT',true);
  463. popusedregisters(pushed);
  464. end;
  465. var
  466. r : preference;
  467. hp : ptree;
  468. l : longint;
  469. ispushed : boolean;
  470. hregister : tregister;
  471. otlabel,oflabel : plabel;
  472. oldpushedparasize : longint;
  473. begin
  474. { save & reset pushedparasize }
  475. oldpushedparasize:=pushedparasize;
  476. pushedparasize:=0;
  477. case p^.inlinenumber of
  478. in_assert_x_y:
  479. begin
  480. otlabel:=truelabel;
  481. oflabel:=falselabel;
  482. getlabel(truelabel);
  483. getlabel(falselabel);
  484. secondpass(p^.left^.left);
  485. if cs_do_assertion in aktlocalswitches then
  486. begin
  487. maketojumpbool(p^.left^.left);
  488. emitl(A_LABEL,falselabel);
  489. { erroraddr }
  490. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,R_EBP)));
  491. { lineno }
  492. exprasmlist^.concat(new(pai386,op_const(A_PUSH,S_L,aktfilepos.line)));
  493. { filename string }
  494. hp:=genstringconstnode(current_module^.sourcefiles^.get_file_name(aktfilepos.fileindex));
  495. secondpass(hp);
  496. if codegenerror then
  497. exit;
  498. emitpushreferenceaddr(exprasmlist,hp^.location.reference);
  499. disposetree(hp);
  500. { push msg }
  501. secondpass(p^.left^.right^.left);
  502. emitpushreferenceaddr(exprasmlist,p^.left^.right^.left^.location.reference);
  503. { call }
  504. emitcall('FPC_ASSERT',true);
  505. emitl(A_LABEL,truelabel);
  506. end;
  507. truelabel:=otlabel;
  508. falselabel:=oflabel;
  509. end;
  510. in_lo_word,
  511. in_hi_word :
  512. begin
  513. secondpass(p^.left);
  514. p^.location.loc:=LOC_REGISTER;
  515. if p^.left^.location.loc<>LOC_REGISTER then
  516. begin
  517. if p^.left^.location.loc=LOC_CREGISTER then
  518. begin
  519. p^.location.register:=reg32toreg16(getregister32);
  520. emit_reg_reg(A_MOV,S_W,p^.left^.location.register,
  521. p^.location.register);
  522. end
  523. else
  524. begin
  525. del_reference(p^.left^.location.reference);
  526. p^.location.register:=reg32toreg16(getregister32);
  527. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_W,newreference(p^.left^.location.reference),
  528. p^.location.register)));
  529. end;
  530. end
  531. else p^.location.register:=p^.left^.location.register;
  532. if p^.inlinenumber=in_hi_word then
  533. exprasmlist^.concat(new(pai386,op_const_reg(A_SHR,S_W,8,p^.location.register)));
  534. p^.location.register:=reg16toreg8(p^.location.register);
  535. end;
  536. in_high_x :
  537. begin
  538. if is_open_array(p^.left^.resulttype) then
  539. begin
  540. secondpass(p^.left);
  541. del_reference(p^.left^.location.reference);
  542. p^.location.register:=getregister32;
  543. new(r);
  544. reset_reference(r^);
  545. r^.base:=highframepointer;
  546. r^.offset:=highoffset+4;
  547. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,
  548. r,p^.location.register)));
  549. end
  550. end;
  551. in_sizeof_x,
  552. in_typeof_x :
  553. begin
  554. { sizeof(openarray) handling }
  555. if (p^.inlinenumber=in_sizeof_x) and
  556. is_open_array(p^.left^.resulttype) then
  557. begin
  558. { sizeof(openarray)=high(openarray)+1 }
  559. secondpass(p^.left);
  560. del_reference(p^.left^.location.reference);
  561. p^.location.register:=getregister32;
  562. new(r);
  563. reset_reference(r^);
  564. r^.base:=highframepointer;
  565. r^.offset:=highoffset+4;
  566. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,
  567. r,p^.location.register)));
  568. exprasmlist^.concat(new(pai386,op_reg(A_INC,S_L,
  569. p^.location.register)));
  570. if parraydef(p^.left^.resulttype)^.elesize<>1 then
  571. exprasmlist^.concat(new(pai386,op_const_reg(A_IMUL,S_L,
  572. parraydef(p^.left^.resulttype)^.elesize,p^.location.register)));
  573. end
  574. else
  575. begin
  576. { for both cases load vmt }
  577. if p^.left^.treetype=typen then
  578. begin
  579. p^.location.register:=getregister32;
  580. exprasmlist^.concat(new(pai386,op_csymbol_reg(A_MOV,
  581. S_L,newcsymbol(pobjectdef(p^.left^.resulttype)^.vmt_mangledname,0),
  582. p^.location.register)));
  583. end
  584. else
  585. begin
  586. secondpass(p^.left);
  587. del_reference(p^.left^.location.reference);
  588. p^.location.loc:=LOC_REGISTER;
  589. p^.location.register:=getregister32;
  590. { load VMT pointer }
  591. inc(p^.left^.location.reference.offset,
  592. pobjectdef(p^.left^.resulttype)^.vmt_offset);
  593. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,
  594. newreference(p^.left^.location.reference),
  595. p^.location.register)));
  596. end;
  597. { in sizeof load size }
  598. if p^.inlinenumber=in_sizeof_x then
  599. begin
  600. new(r);
  601. reset_reference(r^);
  602. r^.base:=p^.location.register;
  603. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,r,
  604. p^.location.register)));
  605. end;
  606. end;
  607. end;
  608. in_lo_long,
  609. in_hi_long :
  610. begin
  611. secondpass(p^.left);
  612. p^.location.loc:=LOC_REGISTER;
  613. if p^.left^.location.loc<>LOC_REGISTER then
  614. begin
  615. if p^.left^.location.loc=LOC_CREGISTER then
  616. begin
  617. p^.location.register:=getregister32;
  618. emit_reg_reg(A_MOV,S_L,p^.left^.location.register,
  619. p^.location.register);
  620. end
  621. else
  622. begin
  623. del_reference(p^.left^.location.reference);
  624. p^.location.register:=getregister32;
  625. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,newreference(p^.left^.location.reference),
  626. p^.location.register)));
  627. end;
  628. end
  629. else p^.location.register:=p^.left^.location.register;
  630. if p^.inlinenumber=in_hi_long then
  631. exprasmlist^.concat(new(pai386,op_const_reg(A_SHR,S_L,16,p^.location.register)));
  632. p^.location.register:=reg32toreg16(p^.location.register);
  633. end;
  634. {***CHARBUG}
  635. {We can now comment them out, as they are handled as typecast.
  636. Saves an incredible amount of 8 bytes code.
  637. I'am not lucky about this, because it's _not_ a type cast (FK) }
  638. { in_ord_char,
  639. in_chr_byte,}
  640. {***}
  641. in_length_string :
  642. begin
  643. secondpass(p^.left);
  644. set_location(p^.location,p^.left^.location);
  645. { length in ansi strings is at offset -8 }
  646. {$ifdef UseAnsiString}
  647. if is_ansistring(p^.left^.resulttype) then
  648. dec(p^.location.reference.offset,8);
  649. {$endif UseAnsiString}
  650. end;
  651. in_pred_x,
  652. in_succ_x:
  653. begin
  654. secondpass(p^.left);
  655. if p^.inlinenumber=in_pred_x then
  656. asmop:=A_DEC
  657. else
  658. asmop:=A_INC;
  659. case p^.resulttype^.size of
  660. 4 : opsize:=S_L;
  661. 2 : opsize:=S_W;
  662. 1 : opsize:=S_B;
  663. else
  664. internalerror(10080);
  665. end;
  666. p^.location.loc:=LOC_REGISTER;
  667. if p^.left^.location.loc<>LOC_REGISTER then
  668. begin
  669. p^.location.register:=getregister32;
  670. if (p^.resulttype^.size=2) then
  671. p^.location.register:=reg32toreg16(p^.location.register);
  672. if (p^.resulttype^.size=1) then
  673. p^.location.register:=reg32toreg8(p^.location.register);
  674. if p^.left^.location.loc=LOC_CREGISTER then
  675. emit_reg_reg(A_MOV,opsize,p^.left^.location.register,
  676. p^.location.register)
  677. else
  678. if p^.left^.location.loc=LOC_FLAGS then
  679. exprasmlist^.concat(new(pai386,op_reg(flag_2_set[p^.left^.location.resflags],S_B,
  680. p^.location.register)))
  681. else
  682. begin
  683. del_reference(p^.left^.location.reference);
  684. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,opsize,newreference(p^.left^.location.reference),
  685. p^.location.register)));
  686. end;
  687. end
  688. else p^.location.register:=p^.left^.location.register;
  689. exprasmlist^.concat(new(pai386,op_reg(asmop,opsize,
  690. p^.location.register)))
  691. { here we should insert bounds check ? }
  692. { and direct call to bounds will crash the program }
  693. { if we are at the limit }
  694. { we could also simply say that pred(first)=first and succ(last)=last }
  695. { could this be usefull I don't think so (PM)
  696. emitoverflowcheck;}
  697. end;
  698. in_dec_x,
  699. in_inc_x :
  700. begin
  701. { set defaults }
  702. addvalue:=1;
  703. addconstant:=true;
  704. { load first parameter, must be a reference }
  705. secondpass(p^.left^.left);
  706. case p^.left^.left^.resulttype^.deftype of
  707. orddef,
  708. enumdef : begin
  709. case p^.left^.left^.resulttype^.size of
  710. 1 : opsize:=S_B;
  711. 2 : opsize:=S_W;
  712. 4 : opsize:=S_L;
  713. end;
  714. end;
  715. pointerdef : begin
  716. opsize:=S_L;
  717. if porddef(ppointerdef(p^.left^.left^.resulttype)^.definition)=voiddef then
  718. addvalue:=1
  719. else
  720. addvalue:=ppointerdef(p^.left^.left^.resulttype)^.definition^.savesize;
  721. end;
  722. else
  723. internalerror(10081);
  724. end;
  725. { second argument specified?, must be a s32bit in register }
  726. if assigned(p^.left^.right) then
  727. begin
  728. secondpass(p^.left^.right^.left);
  729. { when constant, just multiply the addvalue }
  730. if is_constintnode(p^.left^.right^.left) then
  731. addvalue:=addvalue*get_ordinal_value(p^.left^.right^.left)
  732. else
  733. begin
  734. case p^.left^.right^.left^.location.loc of
  735. LOC_REGISTER,
  736. LOC_CREGISTER : hregister:=p^.left^.right^.left^.location.register;
  737. LOC_MEM,
  738. LOC_REFERENCE : begin
  739. del_reference(p^.left^.right^.left^.location.reference);
  740. hregister:=getregister32;
  741. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,
  742. newreference(p^.left^.right^.left^.location.reference),hregister)));
  743. end;
  744. else
  745. internalerror(10082);
  746. end;
  747. { insert multiply with addvalue if its >1 }
  748. if addvalue>1 then
  749. exprasmlist^.concat(new(pai386,op_const_reg(A_IMUL,opsize,
  750. addvalue,hregister)));
  751. addconstant:=false;
  752. end;
  753. end;
  754. { write the add instruction }
  755. if addconstant then
  756. begin
  757. if (addvalue=1) and not(cs_check_overflow in aktlocalswitches) then
  758. begin
  759. if p^.left^.left^.location.loc=LOC_CREGISTER then
  760. exprasmlist^.concat(new(pai386,op_reg(incdecop[p^.inlinenumber],opsize,
  761. p^.left^.left^.location.register)))
  762. else
  763. exprasmlist^.concat(new(pai386,op_ref(incdecop[p^.inlinenumber],opsize,
  764. newreference(p^.left^.left^.location.reference))))
  765. end
  766. else
  767. begin
  768. if p^.left^.left^.location.loc=LOC_CREGISTER then
  769. exprasmlist^.concat(new(pai386,op_const_reg(addsubop[p^.inlinenumber],opsize,
  770. addvalue,p^.left^.left^.location.register)))
  771. else
  772. exprasmlist^.concat(new(pai386,op_const_ref(addsubop[p^.inlinenumber],opsize,
  773. addvalue,newreference(p^.left^.left^.location.reference))));
  774. end
  775. end
  776. else
  777. begin
  778. if p^.left^.left^.location.loc=LOC_CREGISTER then
  779. exprasmlist^.concat(new(pai386,op_reg_reg(addsubop[p^.inlinenumber],opsize,
  780. hregister,p^.left^.left^.location.register)))
  781. else
  782. exprasmlist^.concat(new(pai386,op_reg_ref(addsubop[p^.inlinenumber],opsize,
  783. hregister,newreference(p^.left^.left^.location.reference))));
  784. ungetregister32(hregister);
  785. end;
  786. emitoverflowcheck(p^.left^.left);
  787. end;
  788. in_assigned_x :
  789. begin
  790. secondpass(p^.left^.left);
  791. p^.location.loc:=LOC_FLAGS;
  792. if (p^.left^.left^.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
  793. begin
  794. exprasmlist^.concat(new(pai386,op_reg_reg(A_OR,S_L,
  795. p^.left^.left^.location.register,
  796. p^.left^.left^.location.register)));
  797. ungetregister32(p^.left^.left^.location.register);
  798. end
  799. else
  800. begin
  801. exprasmlist^.concat(new(pai386,op_const_ref(A_CMP,S_L,0,
  802. newreference(p^.left^.left^.location.reference))));
  803. del_reference(p^.left^.left^.location.reference);
  804. end;
  805. p^.location.resflags:=F_NE;
  806. end;
  807. in_reset_typedfile,in_rewrite_typedfile :
  808. begin
  809. pushusedregisters(pushed,$ff);
  810. exprasmlist^.concat(new(pai386,op_const(A_PUSH,S_L,pfiledef(p^.left^.resulttype)^.typed_as^.size)));
  811. secondload(p^.left);
  812. emitpushreferenceaddr(exprasmlist,p^.left^.location.reference);
  813. if p^.inlinenumber=in_reset_typedfile then
  814. emitcall('FPC_RESET_TYPED',true)
  815. else
  816. emitcall('FPC_REWRITE_TYPED',true);
  817. popusedregisters(pushed);
  818. end;
  819. in_write_x :
  820. handlereadwrite(false,false);
  821. in_writeln_x :
  822. handlereadwrite(false,true);
  823. in_read_x :
  824. handlereadwrite(true,false);
  825. in_readln_x :
  826. handlereadwrite(true,true);
  827. in_str_x_string :
  828. begin
  829. handle_str;
  830. maybe_loadesi;
  831. end;
  832. in_include_x_y,
  833. in_exclude_x_y:
  834. begin
  835. secondpass(p^.left^.left);
  836. if p^.left^.right^.left^.treetype=ordconstn then
  837. begin
  838. { calculate bit position }
  839. l:=1 shl (p^.left^.right^.left^.value mod 32);
  840. { determine operator }
  841. if p^.inlinenumber=in_include_x_y then
  842. asmop:=A_OR
  843. else
  844. begin
  845. asmop:=A_AND;
  846. l:=not(l);
  847. end;
  848. if (p^.left^.left^.location.loc=LOC_REFERENCE) then
  849. begin
  850. inc(p^.left^.left^.location.reference.offset,(p^.left^.right^.left^.value div 32)*4);
  851. exprasmlist^.concat(new(pai386,op_const_ref(asmop,S_L,
  852. l,newreference(p^.left^.left^.location.reference))));
  853. del_reference(p^.left^.left^.location.reference);
  854. end
  855. else
  856. { LOC_CREGISTER }
  857. exprasmlist^.concat(new(pai386,op_const_reg(asmop,S_L,
  858. l,p^.left^.left^.location.register)));
  859. end
  860. else
  861. begin
  862. { generate code for the element to set }
  863. ispushed:=maybe_push(p^.left^.right^.left^.registers32,p^.left^.left);
  864. secondpass(p^.left^.right^.left);
  865. if ispushed then
  866. restore(p^.left^.left);
  867. { determine asm operator }
  868. if p^.inlinenumber=in_include_x_y then
  869. asmop:=A_BTS
  870. else
  871. asmop:=A_BTR;
  872. if psetdef(p^.left^.resulttype)^.settype=smallset then
  873. begin
  874. if p^.left^.right^.left^.location.loc in [LOC_CREGISTER,LOC_REGISTER] then
  875. hregister:=p^.left^.right^.left^.location.register
  876. else
  877. begin
  878. hregister:=R_EDI;
  879. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,
  880. newreference(p^.left^.right^.left^.location.reference),R_EDI)));
  881. end;
  882. if (p^.left^.left^.location.loc=LOC_REFERENCE) then
  883. exprasmlist^.concat(new(pai386,op_reg_ref(asmop,S_L,R_EDI,
  884. newreference(p^.left^.right^.left^.location.reference))))
  885. else
  886. exprasmlist^.concat(new(pai386,op_reg_reg(asmop,S_L,R_EDI,
  887. p^.left^.right^.left^.location.register)));
  888. end
  889. else
  890. begin
  891. end;
  892. end;
  893. end;
  894. else internalerror(9);
  895. end;
  896. { reset pushedparasize }
  897. pushedparasize:=oldpushedparasize;
  898. end;
  899. end.
  900. {
  901. $Log$
  902. Revision 1.10 1998-10-05 12:32:44 peter
  903. + assert() support
  904. Revision 1.8 1998/10/02 10:35:09 peter
  905. * support for inc(pointer,value) which now increases with value instead
  906. of 0*value :)
  907. Revision 1.7 1998/09/21 08:45:07 pierre
  908. + added vmt_offset in tobjectdef.write for fututre use
  909. (first steps to have objects without vmt if no virtual !!)
  910. + added fpu_used field for tabstractprocdef :
  911. sets this level to 2 if the functions return with value in FPU
  912. (is then set to correct value at parsing of implementation)
  913. THIS MIGHT refuse some code with FPU expression too complex
  914. that were accepted before and even in some cases
  915. that don't overflow in fact
  916. ( like if f : float; is a forward that finally in implementation
  917. only uses one fpu register !!)
  918. Nevertheless I think that it will improve security on
  919. FPU operations !!
  920. * most other changes only for UseBrowser code
  921. (added symtable references for record and objects)
  922. local switch for refs to args and local of each function
  923. (static symtable still missing)
  924. UseBrowser still not stable and probably broken by
  925. the definition hash array !!
  926. Revision 1.6 1998/09/20 12:26:37 peter
  927. * merged fixes
  928. Revision 1.5 1998/09/17 09:42:15 peter
  929. + pass_2 for cg386
  930. * Message() -> CGMessage() for pass_1/pass_2
  931. Revision 1.4 1998/09/14 10:43:49 peter
  932. * all internal RTL functions start with FPC_
  933. Revision 1.3.2.1 1998/09/20 12:20:07 peter
  934. * Fixed stack not on 4 byte boundary when doing a call
  935. Revision 1.3 1998/09/05 23:03:57 florian
  936. * some fixes to get -Or work:
  937. - inc/dec didn't take care of CREGISTER
  938. - register calculcation of inc/dec was wrong
  939. - var/const parameters get now assigned 32 bit register, but
  940. const parameters only if they are passed by reference !
  941. Revision 1.2 1998/09/04 08:41:40 peter
  942. * updated some error CGMessages
  943. Revision 1.1 1998/08/31 12:22:14 peter
  944. * secondinline moved to cg386inl
  945. Revision 1.19 1998/08/31 08:52:03 peter
  946. * fixed error 10 with succ() and pref()
  947. Revision 1.18 1998/08/20 21:36:38 peter
  948. * fixed 'with object do' bug
  949. Revision 1.17 1998/08/19 16:07:36 jonas
  950. * changed optimizer switches + cleanup of DestroyRefs in daopt386.pas
  951. Revision 1.16 1998/08/18 09:24:36 pierre
  952. * small warning position bug fixed
  953. * support_mmx switches splitting was missing
  954. * rhide error and warning output corrected
  955. Revision 1.15 1998/08/13 11:00:09 peter
  956. * fixed procedure<>procedure construct
  957. Revision 1.14 1998/08/11 14:05:33 peter
  958. * fixed sizeof(array of char)
  959. Revision 1.13 1998/08/10 14:49:45 peter
  960. + localswitches, moduleswitches, globalswitches splitting
  961. Revision 1.12 1998/07/30 13:30:31 florian
  962. * final implemenation of exception support, maybe it needs
  963. some fixes :)
  964. Revision 1.11 1998/07/24 22:16:52 florian
  965. * internal error 10 together with array access fixed. I hope
  966. that's the final fix.
  967. Revision 1.10 1998/07/18 22:54:23 florian
  968. * some ansi/wide/longstring support fixed:
  969. o parameter passing
  970. o returning as result from functions
  971. Revision 1.9 1998/07/07 17:40:37 peter
  972. * packrecords 4 works
  973. * word aligning of parameters
  974. Revision 1.8 1998/07/06 15:51:15 michael
  975. Added length checking for string reading
  976. Revision 1.7 1998/07/06 14:19:51 michael
  977. + Added calls for reading/writing ansistrings
  978. Revision 1.6 1998/07/01 15:28:48 peter
  979. + better writeln/readln handling, now 100% like tp7
  980. Revision 1.5 1998/06/25 14:04:17 peter
  981. + internal inc/dec
  982. Revision 1.4 1998/06/25 08:48:06 florian
  983. * first version of rtti support
  984. Revision 1.3 1998/06/09 16:01:33 pierre
  985. + added procedure directive parsing for procvars
  986. (accepted are popstack cdecl and pascal)
  987. + added C vars with the following syntax
  988. var C calias 'true_c_name';(can be followed by external)
  989. reason is that you must add the Cprefix
  990. which is target dependent
  991. Revision 1.2 1998/06/08 13:13:29 pierre
  992. + temporary variables now in temp_gen.pas unit
  993. because it is processor independent
  994. * mppc68k.bat modified to undefine i386 and support_mmx
  995. (which are defaults for i386)
  996. Revision 1.1 1998/06/05 17:44:10 peter
  997. * splitted cgi386
  998. }