cg386inl.pas 60 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528
  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_1,pass_2,
  29. {$ifndef OLDASM}
  30. i386base,i386asm,
  31. {$else}
  32. i386,
  33. {$endif}
  34. cgai386,tgeni386,cg386cal;
  35. {*****************************************************************************
  36. Helpers
  37. *****************************************************************************}
  38. { reverts the parameter list }
  39. var nb_para : integer;
  40. function reversparameter(p : ptree) : ptree;
  41. var
  42. hp1,hp2 : ptree;
  43. begin
  44. hp1:=nil;
  45. nb_para := 0;
  46. while assigned(p) do
  47. begin
  48. { pull out }
  49. hp2:=p;
  50. p:=p^.right;
  51. inc(nb_para);
  52. { pull in }
  53. hp2^.right:=hp1;
  54. hp1:=hp2;
  55. end;
  56. reversparameter:=hp1;
  57. end;
  58. {*****************************************************************************
  59. SecondInLine
  60. *****************************************************************************}
  61. procedure StoreDirectFuncResult(dest:ptree);
  62. var
  63. hp : ptree;
  64. hdef : porddef;
  65. hreg : tregister;
  66. oldregisterdef : boolean;
  67. begin
  68. SecondPass(dest);
  69. if Codegenerror then
  70. exit;
  71. Case dest^.resulttype^.deftype of
  72. floatdef:
  73. floatstore(PFloatDef(dest^.resulttype)^.typ,dest^.location.reference);
  74. orddef:
  75. begin
  76. Case dest^.resulttype^.size of
  77. 1 : hreg:=regtoreg8(accumulator);
  78. 2 : hreg:=regtoreg16(accumulator);
  79. 4 : hreg:=accumulator;
  80. End;
  81. emit_mov_reg_loc(hreg,dest^.location);
  82. If (cs_check_range in aktlocalswitches) and
  83. {no need to rangecheck longints or cardinals on 32bit processors}
  84. not((porddef(dest^.resulttype)^.typ = s32bit) and
  85. (porddef(dest^.resulttype)^.low = $80000000) and
  86. (porddef(dest^.resulttype)^.high = $7fffffff)) and
  87. not((porddef(dest^.resulttype)^.typ = u32bit) and
  88. (porddef(dest^.resulttype)^.low = 0) and
  89. (porddef(dest^.resulttype)^.high = $ffffffff)) then
  90. Begin
  91. {do not register this temporary def}
  92. OldRegisterDef := RegisterDef;
  93. RegisterDef := False;
  94. hdef:=nil;
  95. Case PordDef(dest^.resulttype)^.typ of
  96. u8bit,u16bit,u32bit:
  97. begin
  98. new(hdef,init(u32bit,0,$ffffffff));
  99. hreg:=accumulator;
  100. end;
  101. s8bit,s16bit,s32bit:
  102. begin
  103. new(hdef,init(s32bit,$80000000,$7fffffff));
  104. hreg:=accumulator;
  105. end;
  106. end;
  107. { create a fake node }
  108. hp := genzeronode(nothingn);
  109. hp^.location.loc := LOC_REGISTER;
  110. hp^.location.register := hreg;
  111. if assigned(hdef) then
  112. hp^.resulttype:=hdef
  113. else
  114. hp^.resulttype:=dest^.resulttype;
  115. { emit the range check }
  116. emitrangecheck(hp,dest^.resulttype);
  117. hp^.right := nil;
  118. if assigned(hdef) then
  119. Dispose(hdef, Done);
  120. RegisterDef := OldRegisterDef;
  121. disposetree(hp);
  122. End;
  123. End;
  124. else
  125. internalerror(66766766);
  126. end;
  127. end;
  128. procedure secondinline(var p : ptree);
  129. const
  130. {tfloattype = (s32real,s64real,s80real,s64bit,f16bit,f32bit);}
  131. { float_name: array[tfloattype] of string[8]=
  132. ('S32REAL','S64REAL','S80REAL','S64BIT','F16BIT','F32BIT'); }
  133. incdecop:array[in_inc_x..in_dec_x] of tasmop=(A_INC,A_DEC);
  134. addsubop:array[in_inc_x..in_dec_x] of tasmop=(A_ADD,A_SUB);
  135. var
  136. aktfile : treference;
  137. ft : tfiletype;
  138. opsize : topsize;
  139. op,
  140. asmop : tasmop;
  141. pushed : tpushed;
  142. {inc/dec}
  143. addconstant : boolean;
  144. addvalue : longint;
  145. procedure handlereadwrite(doread,doln : boolean);
  146. { produces code for READ(LN) and WRITE(LN) }
  147. procedure loadstream;
  148. const
  149. io:array[boolean] of string[7]=('_OUTPUT','_INPUT');
  150. var
  151. r : preference;
  152. begin
  153. new(r);
  154. reset_reference(r^);
  155. r^.symbol:=newasmsymbol('U_'+upper(target_info.system_unit)+io[doread]);
  156. concat_external(r^.symbol^.name,EXT_NEAR);
  157. exprasmlist^.concat(new(pai386,op_ref_reg(A_LEA,S_L,r,R_EDI)))
  158. end;
  159. const
  160. rdwrprefix:array[boolean] of string[15]=('FPC_WRITE_TEXT_','FPC_READ_TEXT_');
  161. var
  162. destpara,
  163. node,hp : ptree;
  164. typedtyp,
  165. pararesult : pdef;
  166. orgfloattype : tfloattype;
  167. has_length : boolean;
  168. dummycoll : tdefcoll;
  169. iolabel : plabel;
  170. npara : longint;
  171. begin
  172. { I/O check }
  173. if (cs_check_io in aktlocalswitches) and
  174. ((aktprocsym^.definition^.options and poiocheck)=0) then
  175. begin
  176. getlabel(iolabel);
  177. emitlab(iolabel);
  178. end
  179. else
  180. iolabel:=nil;
  181. { for write of real with the length specified }
  182. has_length:=false;
  183. hp:=nil;
  184. { reserve temporary pointer to data variable }
  185. aktfile.symbol:=nil;
  186. gettempofsizereference(4,aktfile);
  187. { first state text data }
  188. ft:=ft_text;
  189. { and state a parameter ? }
  190. if p^.left=nil then
  191. begin
  192. { the following instructions are for "writeln;" }
  193. loadstream;
  194. { save @aktfile in temporary variable }
  195. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,S_L,R_EDI,newreference(aktfile))));
  196. end
  197. else
  198. begin
  199. { revers paramters }
  200. node:=reversparameter(p^.left);
  201. p^.left := node;
  202. npara := nb_para;
  203. { calculate data variable }
  204. { is first parameter a file type ? }
  205. if node^.left^.resulttype^.deftype=filedef then
  206. begin
  207. ft:=pfiledef(node^.left^.resulttype)^.filetype;
  208. if ft=ft_typed then
  209. typedtyp:=pfiledef(node^.left^.resulttype)^.typed_as;
  210. secondpass(node^.left);
  211. if codegenerror then
  212. exit;
  213. { save reference in temporary variables }
  214. if node^.left^.location.loc<>LOC_REFERENCE then
  215. begin
  216. CGMessage(cg_e_illegal_expression);
  217. exit;
  218. end;
  219. exprasmlist^.concat(new(pai386,op_ref_reg(A_LEA,S_L,newreference(node^.left^.location.reference),R_EDI)));
  220. { skip to the next parameter }
  221. node:=node^.right;
  222. end
  223. else
  224. begin
  225. { load stdin/stdout stream }
  226. loadstream;
  227. end;
  228. { save @aktfile in temporary variable }
  229. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,S_L,R_EDI,newreference(aktfile))));
  230. if doread then
  231. { parameter by READ gives call by reference }
  232. dummycoll.paratyp:=vs_var
  233. { an WRITE Call by "Const" }
  234. else
  235. dummycoll.paratyp:=vs_const;
  236. { because of secondcallparan, which otherwise attaches }
  237. if ft=ft_typed then
  238. { this is to avoid copy of simple const parameters }
  239. {dummycoll.data:=new(pformaldef,init)}
  240. dummycoll.data:=cformaldef
  241. else
  242. { I think, this isn't a good solution (FK) }
  243. dummycoll.data:=nil;
  244. while assigned(node) do
  245. begin
  246. pushusedregisters(pushed,$ff);
  247. hp:=node;
  248. node:=node^.right;
  249. hp^.right:=nil;
  250. if hp^.is_colon_para then
  251. CGMessage(parser_e_illegal_colon_qualifier);
  252. { when float is written then we need bestreal to be pushed
  253. convert here else we loose the old flaot type }
  254. if (not doread) and
  255. (ft<>ft_typed) and
  256. (hp^.left^.resulttype^.deftype=floatdef) then
  257. begin
  258. orgfloattype:=pfloatdef(hp^.left^.resulttype)^.typ;
  259. hp^.left:=gentypeconvnode(hp^.left,bestrealdef^);
  260. firstpass(hp^.left);
  261. end;
  262. { when read ord,floats are functions, so they need this
  263. parameter as their destination instead of being pushed }
  264. if doread and
  265. (ft<>ft_typed) and
  266. (hp^.resulttype^.deftype in [orddef,floatdef]) then
  267. destpara:=hp^.left
  268. else
  269. begin
  270. if ft=ft_typed then
  271. never_copy_const_param:=true;
  272. { reset data type }
  273. dummycoll.data:=nil;
  274. { create temporary defs for high tree generation }
  275. if doread and (is_shortstring(hp^.resulttype)) then
  276. dummycoll.data:=openshortstringdef
  277. else
  278. if (is_chararray(hp^.resulttype)) then
  279. dummycoll.data:=openchararraydef;
  280. secondcallparan(hp,@dummycoll,false,false,false,0);
  281. if ft=ft_typed then
  282. never_copy_const_param:=false;
  283. end;
  284. hp^.right:=node;
  285. if codegenerror then
  286. exit;
  287. emit_push_mem(aktfile);
  288. if (ft=ft_typed) then
  289. begin
  290. { OK let's try this }
  291. { first we must only allow the right type }
  292. { we have to call blockread or blockwrite }
  293. { but the real problem is that }
  294. { reset and rewrite should have set }
  295. { the type size }
  296. { as recordsize for that file !!!! }
  297. { how can we make that }
  298. { I think that is only possible by adding }
  299. { reset and rewrite to the inline list a call }
  300. { allways read only one record by element }
  301. push_int(typedtyp^.size);
  302. if doread then
  303. emitcall('FPC_TYPED_READ',true)
  304. else
  305. emitcall('FPC_TYPED_WRITE',true);
  306. end
  307. else
  308. begin
  309. { save current position }
  310. pararesult:=hp^.left^.resulttype;
  311. { handle possible field width }
  312. { of course only for write(ln) }
  313. if not doread then
  314. begin
  315. { handle total width parameter }
  316. if assigned(node) and node^.is_colon_para then
  317. begin
  318. hp:=node;
  319. node:=node^.right;
  320. hp^.right:=nil;
  321. secondcallparan(hp,@dummycoll,false,false,false,0);
  322. hp^.right:=node;
  323. if codegenerror then
  324. exit;
  325. has_length:=true;
  326. end
  327. else
  328. if pararesult^.deftype<>floatdef then
  329. push_int(0)
  330. else
  331. push_int(-32767);
  332. { a second colon para for a float ? }
  333. if assigned(node) and node^.is_colon_para then
  334. begin
  335. hp:=node;
  336. node:=node^.right;
  337. hp^.right:=nil;
  338. secondcallparan(hp,@dummycoll,false,false,false,0);
  339. hp^.right:=node;
  340. if pararesult^.deftype<>floatdef then
  341. CGMessage(parser_e_illegal_colon_qualifier);
  342. if codegenerror then
  343. exit;
  344. end
  345. else
  346. begin
  347. if pararesult^.deftype=floatdef then
  348. push_int(-1);
  349. end;
  350. { push also the real type for floats }
  351. if pararesult^.deftype=floatdef then
  352. push_int(ord(orgfloattype));
  353. end;
  354. case pararesult^.deftype of
  355. stringdef :
  356. begin
  357. emitcall(rdwrprefix[doread]+pstringdef(pararesult)^.stringtypname,true);
  358. end;
  359. pointerdef :
  360. begin
  361. if is_pchar(pararesult) then
  362. emitcall(rdwrprefix[doread]+'PCHAR_AS_POINTER',true)
  363. end;
  364. arraydef :
  365. begin
  366. if is_chararray(pararesult) then
  367. emitcall(rdwrprefix[doread]+'PCHAR_AS_ARRAY',true)
  368. end;
  369. floatdef :
  370. begin
  371. emitcall(rdwrprefix[doread]+'FLOAT',true);
  372. if doread then
  373. StoreDirectFuncResult(destpara);
  374. end;
  375. orddef :
  376. begin
  377. case porddef(pararesult)^.typ of
  378. s8bit,s16bit,s32bit :
  379. emitcall(rdwrprefix[doread]+'SINT',true);
  380. u8bit,u16bit,u32bit :
  381. emitcall(rdwrprefix[doread]+'UINT',true);
  382. uchar :
  383. emitcall(rdwrprefix[doread]+'CHAR',true);
  384. s64bitint:
  385. emitcall(rdwrprefix[doread]+'INT64',true);
  386. u64bit :
  387. emitcall(rdwrprefix[doread]+'QWORD',true);
  388. bool8bit,
  389. bool16bit,
  390. bool32bit :
  391. emitcall(rdwrprefix[doread]+'BOOLEAN',true);
  392. end;
  393. if doread then
  394. StoreDirectFuncResult(destpara);
  395. end;
  396. end;
  397. end;
  398. { load ESI in methods again }
  399. popusedregisters(pushed);
  400. maybe_loadesi;
  401. end;
  402. end;
  403. { Insert end of writing for textfiles }
  404. if ft=ft_text then
  405. begin
  406. pushusedregisters(pushed,$ff);
  407. emit_push_mem(aktfile);
  408. if doread then
  409. begin
  410. if doln then
  411. emitcall('FPC_READLN_END',true)
  412. else
  413. emitcall('FPC_READ_END',true);
  414. end
  415. else
  416. begin
  417. if doln then
  418. emitcall('FPC_WRITELN_END',true)
  419. else
  420. emitcall('FPC_WRITE_END',true);
  421. end;
  422. popusedregisters(pushed);
  423. maybe_loadesi;
  424. end;
  425. { Insert IOCheck if set }
  426. if assigned(iolabel) then
  427. begin
  428. { registers are saved in the procedure }
  429. exprasmlist^.concat(new(pai386,op_sym(A_PUSH,S_L,newasmsymbol(lab2str(iolabel)))));
  430. emitcall('FPC_IOCHECK',true);
  431. end;
  432. { Freeup all used temps }
  433. ungetiftemp(aktfile);
  434. if assigned(p^.left) then
  435. begin
  436. p^.left:=reversparameter(p^.left);
  437. if npara<>nb_para then
  438. CGMessage(cg_f_internal_error_in_secondinline);
  439. hp:=p^.left;
  440. while assigned(hp) do
  441. begin
  442. if assigned(hp^.left) then
  443. if (hp^.left^.location.loc in [LOC_MEM,LOC_REFERENCE]) then
  444. ungetiftemp(hp^.left^.location.reference);
  445. hp:=hp^.right;
  446. end;
  447. end;
  448. end;
  449. procedure handle_str;
  450. var
  451. hp,node : ptree;
  452. dummycoll : tdefcoll;
  453. is_real,has_length : boolean;
  454. realtype : tfloattype;
  455. procedureprefix : string;
  456. begin
  457. pushusedregisters(pushed,$ff);
  458. node:=p^.left;
  459. is_real:=false;
  460. has_length:=false;
  461. while assigned(node^.right) do node:=node^.right;
  462. { if a real parameter somewhere then call REALSTR }
  463. if (node^.left^.resulttype^.deftype=floatdef) then
  464. begin
  465. is_real:=true;
  466. realtype:=pfloatdef(node^.left^.resulttype)^.typ;
  467. end;
  468. node:=p^.left;
  469. { we have at least two args }
  470. { with at max 2 colon_para in between }
  471. { string arg }
  472. hp:=node;
  473. node:=node^.right;
  474. hp^.right:=nil;
  475. dummycoll.paratyp:=vs_var;
  476. if is_shortstring(hp^.resulttype) then
  477. dummycoll.data:=openshortstringdef
  478. else
  479. dummycoll.data:=hp^.resulttype;
  480. procedureprefix:='FPC_'+pstringdef(hp^.resulttype)^.stringtypname+'_';
  481. secondcallparan(hp,@dummycoll,false,false,false,0);
  482. if codegenerror then
  483. exit;
  484. dummycoll.paratyp:=vs_const;
  485. disposetree(p^.left);
  486. p^.left:=nil;
  487. { second arg }
  488. hp:=node;
  489. node:=node^.right;
  490. hp^.right:=nil;
  491. { if real push real type }
  492. if is_real then
  493. push_int(ord(realtype));
  494. { frac para }
  495. if hp^.is_colon_para and assigned(node) and
  496. node^.is_colon_para then
  497. begin
  498. dummycoll.data:=hp^.resulttype;
  499. secondcallparan(hp,@dummycoll,false
  500. ,false,false,0
  501. );
  502. if codegenerror then
  503. exit;
  504. disposetree(hp);
  505. hp:=node;
  506. node:=node^.right;
  507. hp^.right:=nil;
  508. has_length:=true;
  509. end
  510. else
  511. if is_real then
  512. push_int(-1);
  513. { third arg, length only if is_real }
  514. if hp^.is_colon_para then
  515. begin
  516. dummycoll.data:=hp^.resulttype;
  517. secondcallparan(hp,@dummycoll,false
  518. ,false,false,0
  519. );
  520. if codegenerror then
  521. exit;
  522. disposetree(hp);
  523. hp:=node;
  524. node:=node^.right;
  525. hp^.right:=nil;
  526. end
  527. else
  528. if is_real then
  529. push_int(-32767)
  530. else
  531. push_int(-1);
  532. { Convert float to bestreal }
  533. if is_real then
  534. begin
  535. hp^.left:=gentypeconvnode(hp^.left,bestrealdef^);
  536. firstpass(hp^.left);
  537. end;
  538. { last arg longint or real }
  539. secondcallparan(hp,@dummycoll,false
  540. ,false,false,0
  541. );
  542. disposetree(hp);
  543. if codegenerror then
  544. exit;
  545. if is_real then
  546. emitcall(procedureprefix+'FLOAT',true)
  547. else
  548. case porddef(hp^.resulttype)^.typ of
  549. u32bit:
  550. emitcall(procedureprefix+'CARDINAL',true);
  551. u64bit:
  552. emitcall(procedureprefix+'QWORD',true);
  553. s64bitint:
  554. emitcall(procedureprefix+'INT64',true);
  555. else
  556. emitcall(procedureprefix+'LONGINT',true);
  557. end;
  558. popusedregisters(pushed);
  559. end;
  560. {$IfnDef OLDVAL}
  561. Procedure Handle_Val;
  562. var
  563. hp,node, code_para, dest_para : ptree;
  564. hreg: TRegister;
  565. hdef: POrdDef;
  566. procedureprefix : string;
  567. hr, hr2: TReference;
  568. dummycoll : tdefcoll;
  569. has_code, has_32bit_code, oldregisterdef: boolean;
  570. begin
  571. node:=p^.left;
  572. hp:=node;
  573. node:=node^.right;
  574. hp^.right:=nil;
  575. {if we have 3 parameters, we have a code parameter}
  576. has_code := Assigned(node^.right);
  577. has_32bit_code := false;
  578. reset_reference(hr);
  579. hreg := R_NO;
  580. If has_code then
  581. Begin
  582. {code is an orddef, that's checked in tcinl}
  583. code_para := hp;
  584. hp := node;
  585. node := node^.right;
  586. hp^.right := nil;
  587. has_32bit_code := (porddef(code_para^.left^.resulttype)^.typ in [u32bit,s32bit]);
  588. End;
  589. {hp = destination now, save for later use}
  590. dest_para := hp;
  591. {if EAX is already in use, it's a register variable. Since we don't
  592. need another register besides EAX, release the one we got}
  593. If hreg <> R_EAX Then ungetregister32(hreg);
  594. {load and push the address of the destination}
  595. dummycoll.paratyp:=vs_var;
  596. dummycoll.data:=dest_para^.resulttype;
  597. secondcallparan(dest_para,@dummycoll,false,false,false,0);
  598. if codegenerror then
  599. exit;
  600. {save the regvars}
  601. pushusedregisters(pushed,$ff);
  602. {now that we've already pushed the addres of dest_para^.left on the
  603. stack, we can put the real parameters on the stack}
  604. If has_32bit_code Then
  605. Begin
  606. dummycoll.paratyp:=vs_var;
  607. dummycoll.data:=code_para^.resulttype;
  608. secondcallparan(code_para,@dummycoll,false,false,false,0);
  609. if codegenerror then
  610. exit;
  611. Disposetree(code_para);
  612. End
  613. Else
  614. Begin
  615. {only 32bit code parameter is supported, so fake one}
  616. GetTempOfSizeReference(4,hr);
  617. emitpushreferenceaddr(exprasmlist,hr);
  618. End;
  619. {node = first parameter = string}
  620. dummycoll.paratyp:=vs_const;
  621. dummycoll.data:=node^.resulttype;
  622. secondcallparan(node,@dummycoll,false,false,false,0);
  623. if codegenerror then
  624. exit;
  625. Case dest_para^.resulttype^.deftype of
  626. floatdef:
  627. procedureprefix := 'FPC_VAL_REAL_';
  628. orddef:
  629. if is_signed(dest_para^.resulttype) then
  630. begin
  631. {if we are converting to a signed number, we have to include the
  632. size of the destination, so the Val function can extend the sign
  633. of the result to allow proper range checking}
  634. exprasmlist^.concat(new(pai386,op_const(A_PUSH,S_L,dest_para^.resulttype^.size)));
  635. procedureprefix := 'FPC_VAL_SINT_'
  636. end
  637. else
  638. procedureprefix := 'FPC_VAL_UINT_';
  639. End;
  640. emitcall(procedureprefix+pstringdef(node^.resulttype)^.stringtypname,true);
  641. { before disposing node we need to ungettemp !! PM }
  642. if node^.left^.location.loc in [LOC_REFERENCE,LOC_MEM] then
  643. ungetiftemp(node^.left^.location.reference);
  644. disposetree(node);
  645. p^.left := nil;
  646. {reload esi in case the dest_para/code_para is a class variable or so}
  647. maybe_loadesi;
  648. If (dest_para^.resulttype^.deftype = orddef) Then
  649. Begin
  650. {store the result in a safe place, because EAX may be used by a
  651. register variable}
  652. hreg := getexplicitregister32(R_EAX);
  653. emit_reg_reg(A_MOV,S_L,R_EAX,hreg);
  654. {as of now, hreg now holds the location of the result, if it was
  655. integer}
  656. End;
  657. { restore the register vars}
  658. popusedregisters(pushed);
  659. If has_code and Not(has_32bit_code) Then
  660. {only 16bit code is possible}
  661. Begin
  662. {load the address of the code parameter}
  663. secondpass(code_para^.left);
  664. {move the code to its destination}
  665. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,NewReference(hr),R_EDI)));
  666. emit_mov_reg_loc(R_DI,code_para^.left^.location);
  667. Disposetree(code_para);
  668. End;
  669. {restore the address of the result}
  670. exprasmlist^.concat(new(pai386,op_reg(A_POP,S_L,R_EDI)));
  671. {set up hr2 to a refernce with EDI as base register}
  672. reset_reference(hr2);
  673. hr2.base := R_EDI;
  674. {save the function result in the destination variable}
  675. Case dest_para^.left^.resulttype^.deftype of
  676. floatdef:
  677. floatstore(PFloatDef(dest_para^.left^.resulttype)^.typ, hr2);
  678. orddef:
  679. Case PordDef(dest_para^.left^.resulttype)^.typ of
  680. u8bit,s8bit:
  681. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV, S_B,
  682. RegToReg8(hreg),newreference(hr2))));
  683. u16bit,s16bit:
  684. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV, S_W,
  685. RegToReg16(hreg),newreference(hr2))));
  686. u32bit,s32bit:
  687. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV, S_L,
  688. hreg,newreference(hr2))));
  689. {u64bit,s64bitint: ???}
  690. End;
  691. End;
  692. If (cs_check_range in aktlocalswitches) and
  693. (dest_para^.left^.resulttype^.deftype = orddef) and
  694. {the following has to be changed to 64bit checking, once Val
  695. returns 64 bit values (unless a special Val function is created
  696. for that)}
  697. {no need to rangecheck longints or cardinals on 32bit processors}
  698. not((porddef(dest_para^.left^.resulttype)^.typ = s32bit) and
  699. (porddef(dest_para^.left^.resulttype)^.low = $80000000) and
  700. (porddef(dest_para^.left^.resulttype)^.high = $7fffffff)) and
  701. not((porddef(dest_para^.left^.resulttype)^.typ = u32bit) and
  702. (porddef(dest_para^.left^.resulttype)^.low = 0) and
  703. (porddef(dest_para^.left^.resulttype)^.high = $ffffffff)) then
  704. Begin
  705. hp := getcopy(dest_para^.left);
  706. hp^.location.loc := LOC_REGISTER;
  707. hp^.location.register := hreg;
  708. {do not register this temporary def}
  709. OldRegisterDef := RegisterDef;
  710. RegisterDef := False;
  711. Case PordDef(dest_para^.left^.resulttype)^.typ of
  712. u8bit,u16bit,u32bit: new(hdef,init(u32bit,0,$ffffffff));
  713. s8bit,s16bit,s32bit: new(hdef,init(s32bit,$80000000,$7fffffff));
  714. end;
  715. hp^.resulttype := hdef;
  716. emitrangecheck(hp,dest_para^.left^.resulttype);
  717. hp^.right := nil;
  718. Dispose(hp^.resulttype, Done);
  719. RegisterDef := OldRegisterDef;
  720. disposetree(hp);
  721. End;
  722. {dest_para^.right is already nil}
  723. disposetree(dest_para);
  724. UnGetIfTemp(hr);
  725. end;
  726. {$EndIf OLDVAL}
  727. var
  728. r : preference;
  729. hp : ptree;
  730. l : longint;
  731. ispushed : boolean;
  732. hregister : tregister;
  733. otlabel,oflabel : plabel;
  734. oldpushedparasize : longint;
  735. begin
  736. { save & reset pushedparasize }
  737. oldpushedparasize:=pushedparasize;
  738. pushedparasize:=0;
  739. case p^.inlinenumber of
  740. in_assert_x_y:
  741. begin
  742. otlabel:=truelabel;
  743. oflabel:=falselabel;
  744. getlabel(truelabel);
  745. getlabel(falselabel);
  746. secondpass(p^.left^.left);
  747. if cs_do_assertion in aktlocalswitches then
  748. begin
  749. maketojumpbool(p^.left^.left);
  750. emitlab(falselabel);
  751. { erroraddr }
  752. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,R_EBP)));
  753. { lineno }
  754. exprasmlist^.concat(new(pai386,op_const(A_PUSH,S_L,aktfilepos.line)));
  755. { filename string }
  756. hp:=genstringconstnode(current_module^.sourcefiles^.get_file_name(aktfilepos.fileindex));
  757. secondpass(hp);
  758. if codegenerror then
  759. exit;
  760. emitpushreferenceaddr(exprasmlist,hp^.location.reference);
  761. disposetree(hp);
  762. { push msg }
  763. secondpass(p^.left^.right^.left);
  764. emitpushreferenceaddr(exprasmlist,p^.left^.right^.left^.location.reference);
  765. { call }
  766. emitcall('FPC_ASSERT',true);
  767. emitlab(truelabel);
  768. end;
  769. freelabel(truelabel);
  770. freelabel(falselabel);
  771. truelabel:=otlabel;
  772. falselabel:=oflabel;
  773. end;
  774. in_lo_word,
  775. in_hi_word :
  776. begin
  777. secondpass(p^.left);
  778. p^.location.loc:=LOC_REGISTER;
  779. if p^.left^.location.loc<>LOC_REGISTER then
  780. begin
  781. if p^.left^.location.loc=LOC_CREGISTER then
  782. begin
  783. p^.location.register:=reg32toreg16(getregister32);
  784. emit_reg_reg(A_MOV,S_W,p^.left^.location.register,
  785. p^.location.register);
  786. end
  787. else
  788. begin
  789. del_reference(p^.left^.location.reference);
  790. p^.location.register:=reg32toreg16(getregister32);
  791. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_W,newreference(p^.left^.location.reference),
  792. p^.location.register)));
  793. end;
  794. end
  795. else p^.location.register:=p^.left^.location.register;
  796. if p^.inlinenumber=in_hi_word then
  797. exprasmlist^.concat(new(pai386,op_const_reg(A_SHR,S_W,8,p^.location.register)));
  798. p^.location.register:=reg16toreg8(p^.location.register);
  799. end;
  800. in_sizeof_x,
  801. in_typeof_x :
  802. begin
  803. { for both cases load vmt }
  804. if p^.left^.treetype=typen then
  805. begin
  806. p^.location.register:=getregister32;
  807. exprasmlist^.concat(new(pai386,op_sym_ofs_reg(A_MOV,
  808. S_L,newasmsymbol(pobjectdef(p^.left^.resulttype)^.vmt_mangledname),0,
  809. p^.location.register)));
  810. end
  811. else
  812. begin
  813. secondpass(p^.left);
  814. del_reference(p^.left^.location.reference);
  815. p^.location.loc:=LOC_REGISTER;
  816. p^.location.register:=getregister32;
  817. { load VMT pointer }
  818. inc(p^.left^.location.reference.offset,
  819. pobjectdef(p^.left^.resulttype)^.vmt_offset);
  820. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,
  821. newreference(p^.left^.location.reference),
  822. p^.location.register)));
  823. end;
  824. { in sizeof load size }
  825. if p^.inlinenumber=in_sizeof_x then
  826. begin
  827. new(r);
  828. reset_reference(r^);
  829. r^.base:=p^.location.register;
  830. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,r,
  831. p^.location.register)));
  832. end;
  833. end;
  834. in_lo_long,
  835. in_hi_long :
  836. begin
  837. secondpass(p^.left);
  838. p^.location.loc:=LOC_REGISTER;
  839. if p^.left^.location.loc<>LOC_REGISTER then
  840. begin
  841. if p^.left^.location.loc=LOC_CREGISTER then
  842. begin
  843. p^.location.register:=getregister32;
  844. emit_reg_reg(A_MOV,S_L,p^.left^.location.register,
  845. p^.location.register);
  846. end
  847. else
  848. begin
  849. del_reference(p^.left^.location.reference);
  850. p^.location.register:=getregister32;
  851. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,newreference(p^.left^.location.reference),
  852. p^.location.register)));
  853. end;
  854. end
  855. else p^.location.register:=p^.left^.location.register;
  856. if p^.inlinenumber=in_hi_long then
  857. exprasmlist^.concat(new(pai386,op_const_reg(A_SHR,S_L,16,p^.location.register)));
  858. p^.location.register:=reg32toreg16(p^.location.register);
  859. end;
  860. in_length_string :
  861. begin
  862. secondpass(p^.left);
  863. set_location(p^.location,p^.left^.location);
  864. { length in ansi strings is at offset -8 }
  865. if is_ansistring(p^.left^.resulttype) then
  866. dec(p^.location.reference.offset,8)
  867. { char is always 1, so make it a constant value }
  868. else if is_char(p^.left^.resulttype) then
  869. begin
  870. clear_location(p^.location);
  871. p^.location.loc:=LOC_MEM;
  872. p^.location.reference.is_immediate:=true;
  873. p^.location.reference.offset:=1;
  874. end;
  875. end;
  876. in_pred_x,
  877. in_succ_x:
  878. begin
  879. secondpass(p^.left);
  880. if not (cs_check_overflow in aktlocalswitches) then
  881. if p^.inlinenumber=in_pred_x then
  882. asmop:=A_DEC
  883. else
  884. asmop:=A_INC
  885. else
  886. if p^.inlinenumber=in_pred_x then
  887. asmop:=A_SUB
  888. else
  889. asmop:=A_ADD;
  890. case p^.resulttype^.size of
  891. 4 : opsize:=S_L;
  892. 2 : opsize:=S_W;
  893. 1 : opsize:=S_B;
  894. else
  895. internalerror(10080);
  896. end;
  897. p^.location.loc:=LOC_REGISTER;
  898. if p^.left^.location.loc<>LOC_REGISTER then
  899. begin
  900. p^.location.register:=getregister32;
  901. if (p^.resulttype^.size=2) then
  902. p^.location.register:=reg32toreg16(p^.location.register);
  903. if (p^.resulttype^.size=1) then
  904. p^.location.register:=reg32toreg8(p^.location.register);
  905. if p^.left^.location.loc=LOC_CREGISTER then
  906. emit_reg_reg(A_MOV,opsize,p^.left^.location.register,
  907. p^.location.register)
  908. else
  909. if p^.left^.location.loc=LOC_FLAGS then
  910. emit_flag2reg(p^.left^.location.resflags,p^.location.register)
  911. else
  912. begin
  913. del_reference(p^.left^.location.reference);
  914. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,opsize,newreference(p^.left^.location.reference),
  915. p^.location.register)));
  916. end;
  917. end
  918. else p^.location.register:=p^.left^.location.register;
  919. if not (cs_check_overflow in aktlocalswitches) then
  920. exprasmlist^.concat(new(pai386,op_reg(asmop,opsize,
  921. p^.location.register)))
  922. else
  923. exprasmlist^.concat(new(pai386,op_const_reg(asmop,opsize,1,
  924. p^.location.register)));
  925. emitoverflowcheck(p);
  926. emitrangecheck(p,p^.resulttype);
  927. end;
  928. in_dec_x,
  929. in_inc_x :
  930. begin
  931. { set defaults }
  932. addvalue:=1;
  933. addconstant:=true;
  934. { load first parameter, must be a reference }
  935. secondpass(p^.left^.left);
  936. case p^.left^.left^.resulttype^.deftype of
  937. orddef,
  938. enumdef : begin
  939. case p^.left^.left^.resulttype^.size of
  940. 1 : opsize:=S_B;
  941. 2 : opsize:=S_W;
  942. 4 : opsize:=S_L;
  943. end;
  944. end;
  945. pointerdef : begin
  946. opsize:=S_L;
  947. if porddef(ppointerdef(p^.left^.left^.resulttype)^.definition)=voiddef then
  948. addvalue:=1
  949. else
  950. addvalue:=ppointerdef(p^.left^.left^.resulttype)^.definition^.savesize;
  951. end;
  952. else
  953. internalerror(10081);
  954. end;
  955. { second argument specified?, must be a s32bit in register }
  956. if assigned(p^.left^.right) then
  957. begin
  958. secondpass(p^.left^.right^.left);
  959. { when constant, just multiply the addvalue }
  960. if is_constintnode(p^.left^.right^.left) then
  961. addvalue:=addvalue*get_ordinal_value(p^.left^.right^.left)
  962. else
  963. begin
  964. case p^.left^.right^.left^.location.loc of
  965. LOC_REGISTER,
  966. LOC_CREGISTER : hregister:=p^.left^.right^.left^.location.register;
  967. LOC_MEM,
  968. LOC_REFERENCE : begin
  969. del_reference(p^.left^.right^.left^.location.reference);
  970. hregister:=getregister32;
  971. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,
  972. newreference(p^.left^.right^.left^.location.reference),hregister)));
  973. end;
  974. else
  975. internalerror(10082);
  976. end;
  977. { insert multiply with addvalue if its >1 }
  978. if addvalue>1 then
  979. exprasmlist^.concat(new(pai386,op_const_reg(A_IMUL,opsize,
  980. addvalue,hregister)));
  981. addconstant:=false;
  982. end;
  983. end;
  984. { write the add instruction }
  985. if addconstant then
  986. begin
  987. if (addvalue=1) and not(cs_check_overflow in aktlocalswitches) then
  988. begin
  989. if p^.left^.left^.location.loc=LOC_CREGISTER then
  990. exprasmlist^.concat(new(pai386,op_reg(incdecop[p^.inlinenumber],opsize,
  991. p^.left^.left^.location.register)))
  992. else
  993. exprasmlist^.concat(new(pai386,op_ref(incdecop[p^.inlinenumber],opsize,
  994. newreference(p^.left^.left^.location.reference))))
  995. end
  996. else
  997. begin
  998. if p^.left^.left^.location.loc=LOC_CREGISTER then
  999. exprasmlist^.concat(new(pai386,op_const_reg(addsubop[p^.inlinenumber],opsize,
  1000. addvalue,p^.left^.left^.location.register)))
  1001. else
  1002. exprasmlist^.concat(new(pai386,op_const_ref(addsubop[p^.inlinenumber],opsize,
  1003. addvalue,newreference(p^.left^.left^.location.reference))));
  1004. end
  1005. end
  1006. else
  1007. begin
  1008. { BUG HERE : detected with nasm :
  1009. hregister is allways 32 bit
  1010. it should be converted to 16 or 8 bit depending on op_size PM }
  1011. { still not perfect :
  1012. if hregister is already a 16 bit reg ?? PM }
  1013. case opsize of
  1014. S_B : hregister:=reg32toreg8(hregister);
  1015. S_W : hregister:=reg32toreg16(hregister);
  1016. end;
  1017. if p^.left^.left^.location.loc=LOC_CREGISTER then
  1018. exprasmlist^.concat(new(pai386,op_reg_reg(addsubop[p^.inlinenumber],opsize,
  1019. hregister,p^.left^.left^.location.register)))
  1020. else
  1021. exprasmlist^.concat(new(pai386,op_reg_ref(addsubop[p^.inlinenumber],opsize,
  1022. hregister,newreference(p^.left^.left^.location.reference))));
  1023. case opsize of
  1024. S_B : hregister:=reg8toreg32(hregister);
  1025. S_W : hregister:=reg16toreg32(hregister);
  1026. end;
  1027. ungetregister32(hregister);
  1028. end;
  1029. emitoverflowcheck(p^.left^.left);
  1030. emitrangecheck(p^.left^.left,p^.left^.left^.resulttype);
  1031. end;
  1032. in_assigned_x :
  1033. begin
  1034. secondpass(p^.left^.left);
  1035. p^.location.loc:=LOC_FLAGS;
  1036. if (p^.left^.left^.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
  1037. begin
  1038. exprasmlist^.concat(new(pai386,op_reg_reg(A_OR,S_L,
  1039. p^.left^.left^.location.register,
  1040. p^.left^.left^.location.register)));
  1041. ungetregister32(p^.left^.left^.location.register);
  1042. end
  1043. else
  1044. begin
  1045. exprasmlist^.concat(new(pai386,op_const_ref(A_CMP,S_L,0,
  1046. newreference(p^.left^.left^.location.reference))));
  1047. del_reference(p^.left^.left^.location.reference);
  1048. end;
  1049. p^.location.resflags:=F_NE;
  1050. end;
  1051. in_reset_typedfile,in_rewrite_typedfile :
  1052. begin
  1053. pushusedregisters(pushed,$ff);
  1054. exprasmlist^.concat(new(pai386,op_const(A_PUSH,S_L,pfiledef(p^.left^.resulttype)^.typed_as^.size)));
  1055. secondpass(p^.left);
  1056. emitpushreferenceaddr(exprasmlist,p^.left^.location.reference);
  1057. if p^.inlinenumber=in_reset_typedfile then
  1058. emitcall('FPC_RESET_TYPED',true)
  1059. else
  1060. emitcall('FPC_REWRITE_TYPED',true);
  1061. popusedregisters(pushed);
  1062. end;
  1063. in_write_x :
  1064. handlereadwrite(false,false);
  1065. in_writeln_x :
  1066. handlereadwrite(false,true);
  1067. in_read_x :
  1068. handlereadwrite(true,false);
  1069. in_readln_x :
  1070. handlereadwrite(true,true);
  1071. in_str_x_string :
  1072. begin
  1073. handle_str;
  1074. maybe_loadesi;
  1075. end;
  1076. {$IfnDef OLDVAL}
  1077. in_val_x :
  1078. Begin
  1079. handle_val;
  1080. End;
  1081. {$EndIf OLDVAL}
  1082. in_include_x_y,
  1083. in_exclude_x_y:
  1084. begin
  1085. secondpass(p^.left^.left);
  1086. if p^.left^.right^.left^.treetype=ordconstn then
  1087. begin
  1088. { calculate bit position }
  1089. l:=1 shl (p^.left^.right^.left^.value mod 32);
  1090. { determine operator }
  1091. if p^.inlinenumber=in_include_x_y then
  1092. asmop:=A_OR
  1093. else
  1094. begin
  1095. asmop:=A_AND;
  1096. l:=not(l);
  1097. end;
  1098. if (p^.left^.left^.location.loc=LOC_REFERENCE) then
  1099. begin
  1100. inc(p^.left^.left^.location.reference.offset,(p^.left^.right^.left^.value div 32)*4);
  1101. exprasmlist^.concat(new(pai386,op_const_ref(asmop,S_L,
  1102. l,newreference(p^.left^.left^.location.reference))));
  1103. del_reference(p^.left^.left^.location.reference);
  1104. end
  1105. else
  1106. { LOC_CREGISTER }
  1107. exprasmlist^.concat(new(pai386,op_const_reg(asmop,S_L,
  1108. l,p^.left^.left^.location.register)));
  1109. end
  1110. else
  1111. begin
  1112. { generate code for the element to set }
  1113. ispushed:=maybe_push(p^.left^.right^.left^.registers32,p^.left^.left);
  1114. secondpass(p^.left^.right^.left);
  1115. if ispushed then
  1116. restore(p^.left^.left);
  1117. { determine asm operator }
  1118. if p^.inlinenumber=in_include_x_y then
  1119. asmop:=A_BTS
  1120. else
  1121. asmop:=A_BTR;
  1122. if psetdef(p^.left^.resulttype)^.settype=smallset then
  1123. begin
  1124. if p^.left^.right^.left^.location.loc in [LOC_CREGISTER,LOC_REGISTER] then
  1125. hregister:=p^.left^.right^.left^.location.register
  1126. else
  1127. begin
  1128. hregister:=R_EDI;
  1129. opsize:=def2def_opsize(p^.left^.right^.left^.resulttype,u32bitdef);
  1130. if opsize in [S_B,S_W,S_L] then
  1131. op:=A_MOV
  1132. else
  1133. op:=A_MOVZX;
  1134. exprasmlist^.concat(new(pai386,op_ref_reg(op,opsize,
  1135. newreference(p^.left^.right^.left^.location.reference),R_EDI)));
  1136. end;
  1137. if (p^.left^.left^.location.loc=LOC_REFERENCE) then
  1138. exprasmlist^.concat(new(pai386,op_reg_ref(asmop,S_L,hregister,
  1139. newreference(p^.left^.right^.left^.location.reference))))
  1140. else
  1141. exprasmlist^.concat(new(pai386,op_reg_reg(asmop,S_L,hregister,
  1142. p^.left^.right^.left^.location.register)));
  1143. end
  1144. else
  1145. begin
  1146. pushsetelement(p^.left^.right^.left);
  1147. { normset is allways a ref }
  1148. emitpushreferenceaddr(exprasmlist,
  1149. p^.left^.left^.location.reference);
  1150. if p^.inlinenumber=in_include_x_y then
  1151. emitcall('FPC_SET_SET_BYTE',true)
  1152. else
  1153. emitcall('FPC_SET_UNSET_BYTE',true);
  1154. {CGMessage(cg_e_include_not_implemented);}
  1155. end;
  1156. end;
  1157. end;
  1158. else internalerror(9);
  1159. end;
  1160. { remove temp. objects, we don't generate them here }
  1161. removetemps(exprasmlist,temptoremove);
  1162. temptoremove^.clear;
  1163. { reset pushedparasize }
  1164. pushedparasize:=oldpushedparasize;
  1165. end;
  1166. end.
  1167. {
  1168. $Log$
  1169. Revision 1.48 1999-05-12 00:19:42 peter
  1170. * removed R_DEFAULT_SEG
  1171. * uniform float names
  1172. Revision 1.47 1999/05/06 09:05:13 peter
  1173. * generic write_float and str_float
  1174. * fixed constant float conversions
  1175. Revision 1.46 1999/05/05 16:18:20 jonas
  1176. * changes to handle_val so register vars are pushed/poped only once
  1177. Revision 1.45 1999/05/01 13:24:08 peter
  1178. * merged nasm compiler
  1179. * old asm moved to oldasm/
  1180. Revision 1.44 1999/04/26 18:28:13 peter
  1181. * better read/write array
  1182. Revision 1.43 1999/04/19 09:45:48 pierre
  1183. + cdecl or stdcall push all args with longint size
  1184. * tempansi stuff cleaned up
  1185. Revision 1.42 1999/04/14 09:11:59 peter
  1186. * fixed include
  1187. Revision 1.41 1999/04/08 23:59:49 pierre
  1188. * temp string for val code freed
  1189. Revision 1.40 1999/04/08 15:57:46 peter
  1190. + subrange checking for readln()
  1191. Revision 1.39 1999/04/07 15:31:16 pierre
  1192. * all formaldefs are now a sinlge definition
  1193. cformaldef (this was necessary for double_checksum)
  1194. + small part of double_checksum code
  1195. Revision 1.38 1999/04/05 11:07:26 jonas
  1196. * fixed some typos in the constants of the range checking for Val
  1197. Revision 1.37 1999/04/01 22:07:51 peter
  1198. * universal string names (ansistr instead of stransi) for val/str
  1199. Revision 1.36 1999/04/01 06:21:04 jonas
  1200. * added initialization for has_32bit_code (caused problems with Val statement
  1201. without code parameter)
  1202. Revision 1.35 1999/03/31 20:30:49 michael
  1203. * fixed typo: odlval to oldval
  1204. Revision 1.34 1999/03/31 17:13:09 jonas
  1205. * bugfix for -Ox with internal val code
  1206. * internal val code now requires less free registers
  1207. * internal val code no longer needs a temp var for range checking
  1208. Revision 1.33 1999/03/26 00:24:15 peter
  1209. * last para changed to long for easier pushing with 4 byte aligns
  1210. Revision 1.32 1999/03/26 00:05:26 peter
  1211. * released valintern
  1212. + deffile is now removed when compiling is finished
  1213. * ^( compiles now correct
  1214. + static directive
  1215. * shrd fixed
  1216. Revision 1.31 1999/03/24 23:16:49 peter
  1217. * fixed bugs 212,222,225,227,229,231,233
  1218. Revision 1.30 1999/03/16 17:52:56 jonas
  1219. * changes for internal Val code (do a "make cycle OPT=-dvalintern" to test)
  1220. * in cgi386inl: also range checking for subrange types (compile with "-dreadrangecheck")
  1221. * in cgai386: also small fixes to emitrangecheck
  1222. Revision 1.29 1999/02/25 21:02:27 peter
  1223. * ag386bin updates
  1224. + coff writer
  1225. Revision 1.28 1999/02/22 02:15:11 peter
  1226. * updates for ag386bin
  1227. Revision 1.27 1999/02/17 14:21:40 pierre
  1228. * unused local removed
  1229. Revision 1.26 1999/02/15 11:40:21 pierre
  1230. * pred/succ with overflow check must use ADD DEC !!
  1231. Revision 1.25 1999/02/05 10:56:19 florian
  1232. * in some cases a writeln of temp. ansistrings cause a memory leak, fixed
  1233. Revision 1.24 1999/01/21 22:10:39 peter
  1234. * fixed array of const
  1235. * generic platform independent high() support
  1236. Revision 1.23 1999/01/06 12:23:29 florian
  1237. * str(...) for ansi/long and widestrings fixed
  1238. Revision 1.22 1998/12/11 23:36:07 florian
  1239. + again more stuff for int64/qword:
  1240. - comparision operators
  1241. - code generation for: str, read(ln), write(ln)
  1242. Revision 1.21 1998/12/11 00:02:50 peter
  1243. + globtype,tokens,version unit splitted from globals
  1244. Revision 1.20 1998/11/27 14:50:32 peter
  1245. + open strings, $P switch support
  1246. Revision 1.19 1998/11/26 13:10:40 peter
  1247. * new int - int conversion -dNEWCNV
  1248. * some function renamings
  1249. Revision 1.18 1998/11/24 17:04:27 peter
  1250. * fixed length(char) when char is a variable
  1251. Revision 1.17 1998/11/05 12:02:33 peter
  1252. * released useansistring
  1253. * removed -Sv, its now available in fpc modes
  1254. Revision 1.16 1998/10/22 17:11:13 pierre
  1255. + terminated the include exclude implementation for i386
  1256. * enums inside records fixed
  1257. Revision 1.15 1998/10/21 15:12:50 pierre
  1258. * bug fix for IOCHECK inside a procedure with iocheck modifier
  1259. * removed the GPF for unexistant overloading
  1260. (firstcall was called with procedinition=nil !)
  1261. * changed typen to what Florian proposed
  1262. gentypenode(p : pdef) sets the typenodetype field
  1263. and resulttype is only set if inside bt_type block !
  1264. Revision 1.14 1998/10/20 08:06:40 pierre
  1265. * several memory corruptions due to double freemem solved
  1266. => never use p^.loc.location:=p^.left^.loc.location;
  1267. + finally I added now by default
  1268. that ra386dir translates global and unit symbols
  1269. + added a first field in tsymtable and
  1270. a nextsym field in tsym
  1271. (this allows to obtain ordered type info for
  1272. records and objects in gdb !)
  1273. Revision 1.13 1998/10/13 16:50:02 pierre
  1274. * undid some changes of Peter that made the compiler wrong
  1275. for m68k (I had to reinsert some ifdefs)
  1276. * removed several memory leaks under m68k
  1277. * removed the meory leaks for assembler readers
  1278. * cross compiling shoud work again better
  1279. ( crosscompiling sysamiga works
  1280. but as68k still complain about some code !)
  1281. Revision 1.12 1998/10/08 17:17:12 pierre
  1282. * current_module old scanner tagged as invalid if unit is recompiled
  1283. + added ppheap for better info on tracegetmem of heaptrc
  1284. (adds line column and file index)
  1285. * several memory leaks removed ith help of heaptrc !!
  1286. Revision 1.11 1998/10/05 21:33:15 peter
  1287. * fixed 161,165,166,167,168
  1288. Revision 1.10 1998/10/05 12:32:44 peter
  1289. + assert() support
  1290. Revision 1.8 1998/10/02 10:35:09 peter
  1291. * support for inc(pointer,value) which now increases with value instead
  1292. of 0*value :)
  1293. Revision 1.7 1998/09/21 08:45:07 pierre
  1294. + added vmt_offset in tobjectdef.write for fututre use
  1295. (first steps to have objects without vmt if no virtual !!)
  1296. + added fpu_used field for tabstractprocdef :
  1297. sets this level to 2 if the functions return with value in FPU
  1298. (is then set to correct value at parsing of implementation)
  1299. THIS MIGHT refuse some code with FPU expression too complex
  1300. that were accepted before and even in some cases
  1301. that don't overflow in fact
  1302. ( like if f : float; is a forward that finally in implementation
  1303. only uses one fpu register !!)
  1304. Nevertheless I think that it will improve security on
  1305. FPU operations !!
  1306. * most other changes only for UseBrowser code
  1307. (added symtable references for record and objects)
  1308. local switch for refs to args and local of each function
  1309. (static symtable still missing)
  1310. UseBrowser still not stable and probably broken by
  1311. the definition hash array !!
  1312. Revision 1.6 1998/09/20 12:26:37 peter
  1313. * merged fixes
  1314. Revision 1.5 1998/09/17 09:42:15 peter
  1315. + pass_2 for cg386
  1316. * Message() -> CGMessage() for pass_1/pass_2
  1317. Revision 1.4 1998/09/14 10:43:49 peter
  1318. * all internal RTL functions start with FPC_
  1319. Revision 1.3.2.1 1998/09/20 12:20:07 peter
  1320. * Fixed stack not on 4 byte boundary when doing a call
  1321. Revision 1.3 1998/09/05 23:03:57 florian
  1322. * some fixes to get -Or work:
  1323. - inc/dec didn't take care of CREGISTER
  1324. - register calculcation of inc/dec was wrong
  1325. - var/const parameters get now assigned 32 bit register, but
  1326. const parameters only if they are passed by reference !
  1327. Revision 1.2 1998/09/04 08:41:40 peter
  1328. * updated some error CGMessages
  1329. Revision 1.1 1998/08/31 12:22:14 peter
  1330. * secondinline moved to cg386inl
  1331. Revision 1.19 1998/08/31 08:52:03 peter
  1332. * fixed error 10 with succ() and pref()
  1333. Revision 1.18 1998/08/20 21:36:38 peter
  1334. * fixed 'with object do' bug
  1335. Revision 1.17 1998/08/19 16:07:36 jonas
  1336. * changed optimizer switches + cleanup of DestroyRefs in daopt386.pas
  1337. Revision 1.16 1998/08/18 09:24:36 pierre
  1338. * small warning position bug fixed
  1339. * support_mmx switches splitting was missing
  1340. * rhide error and warning output corrected
  1341. Revision 1.15 1998/08/13 11:00:09 peter
  1342. * fixed procedure<>procedure construct
  1343. Revision 1.14 1998/08/11 14:05:33 peter
  1344. * fixed sizeof(array of char)
  1345. Revision 1.13 1998/08/10 14:49:45 peter
  1346. + localswitches, moduleswitches, globalswitches splitting
  1347. Revision 1.12 1998/07/30 13:30:31 florian
  1348. * final implemenation of exception support, maybe it needs
  1349. some fixes :)
  1350. Revision 1.11 1998/07/24 22:16:52 florian
  1351. * internal error 10 together with array access fixed. I hope
  1352. that's the final fix.
  1353. Revision 1.10 1998/07/18 22:54:23 florian
  1354. * some ansi/wide/longstring support fixed:
  1355. o parameter passing
  1356. o returning as result from functions
  1357. Revision 1.9 1998/07/07 17:40:37 peter
  1358. * packrecords 4 works
  1359. * word aligning of parameters
  1360. Revision 1.8 1998/07/06 15:51:15 michael
  1361. Added length checking for string reading
  1362. Revision 1.7 1998/07/06 14:19:51 michael
  1363. + Added calls for reading/writing ansistrings
  1364. Revision 1.6 1998/07/01 15:28:48 peter
  1365. + better writeln/readln handling, now 100% like tp7
  1366. Revision 1.5 1998/06/25 14:04:17 peter
  1367. + internal inc/dec
  1368. Revision 1.4 1998/06/25 08:48:06 florian
  1369. * first version of rtti support
  1370. Revision 1.3 1998/06/09 16:01:33 pierre
  1371. + added procedure directive parsing for procvars
  1372. (accepted are popstack cdecl and pascal)
  1373. + added C vars with the following syntax
  1374. var C calias 'true_c_name';(can be followed by external)
  1375. reason is that you must add the Cprefix
  1376. which is target dependent
  1377. Revision 1.2 1998/06/08 13:13:29 pierre
  1378. + temporary variables now in temp_gen.pas unit
  1379. because it is processor independent
  1380. * mppc68k.bat modified to undefine i386 and support_mmx
  1381. (which are defaults for i386)
  1382. Revision 1.1 1998/06/05 17:44:10 peter
  1383. * splitted cgi386
  1384. }