cg386inl.pas 48 KB

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