cg386inl.pas 62 KB

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