cg386inl.pas 66 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708
  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. symconst,symtable,aasm,types,
  28. hcodegen,temp_gen,pass_1,pass_2,
  29. cpubase,cpuasm,
  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,s64bit] 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. emit_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. not(po_iocheck in aktprocsym^.definition^.procoptions) 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. emit_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. emit_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. emit_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 pfloatdef(p^.resulttype)^.typ<>f32bit then
  385. inc(fpuvaroffset);
  386. if doread then
  387. StoreDirectFuncResult(hp^.left);
  388. end;
  389. orddef :
  390. begin
  391. case porddef(pararesult)^.typ of
  392. s8bit,s16bit,s32bit :
  393. emitcall(rdwrprefix[doread]+'SINT');
  394. u8bit,u16bit,u32bit :
  395. emitcall(rdwrprefix[doread]+'UINT');
  396. uchar :
  397. emitcall(rdwrprefix[doread]+'CHAR');
  398. s64bit :
  399. emitcall(rdwrprefix[doread]+'INT64');
  400. u64bit :
  401. emitcall(rdwrprefix[doread]+'QWORD');
  402. bool8bit,
  403. bool16bit,
  404. bool32bit :
  405. emitcall(rdwrprefix[doread]+'BOOLEAN');
  406. end;
  407. if doread then
  408. StoreDirectFuncResult(hp^.left);
  409. end;
  410. end;
  411. end;
  412. { load ESI in methods again }
  413. popusedregisters(pushed);
  414. maybe_loadesi;
  415. end;
  416. end;
  417. { Insert end of writing for textfiles }
  418. if ft=ft_text then
  419. begin
  420. pushusedregisters(pushed,$ff);
  421. emit_push_mem(aktfile);
  422. if doread then
  423. begin
  424. if doln then
  425. emitcall('FPC_READLN_END')
  426. else
  427. emitcall('FPC_READ_END');
  428. end
  429. else
  430. begin
  431. if doln then
  432. emitcall('FPC_WRITELN_END')
  433. else
  434. emitcall('FPC_WRITE_END');
  435. end;
  436. popusedregisters(pushed);
  437. maybe_loadesi;
  438. end;
  439. { Insert IOCheck if set }
  440. if assigned(iolabel) then
  441. begin
  442. { registers are saved in the procedure }
  443. emit_sym(A_PUSH,S_L,iolabel);
  444. emitcall('FPC_IOCHECK');
  445. end;
  446. { Freeup all used temps }
  447. ungetiftemp(aktfile);
  448. if assigned(p^.left) then
  449. begin
  450. p^.left:=reversparameter(p^.left);
  451. if npara<>nb_para then
  452. CGMessage(cg_f_internal_error_in_secondinline);
  453. hp:=p^.left;
  454. while assigned(hp) do
  455. begin
  456. if assigned(hp^.left) then
  457. if (hp^.left^.location.loc in [LOC_MEM,LOC_REFERENCE]) then
  458. ungetiftemp(hp^.left^.location.reference);
  459. hp:=hp^.right;
  460. end;
  461. end;
  462. end;
  463. procedure handle_str;
  464. var
  465. hp,node : ptree;
  466. dummycoll : tdefcoll;
  467. is_real,has_length : boolean;
  468. realtype : tfloattype;
  469. procedureprefix : string;
  470. begin
  471. dummycoll.register:=R_NO;
  472. pushusedregisters(pushed,$ff);
  473. node:=p^.left;
  474. is_real:=false;
  475. has_length:=false;
  476. while assigned(node^.right) do node:=node^.right;
  477. { if a real parameter somewhere then call REALSTR }
  478. if (node^.left^.resulttype^.deftype=floatdef) then
  479. begin
  480. is_real:=true;
  481. realtype:=pfloatdef(node^.left^.resulttype)^.typ;
  482. end;
  483. node:=p^.left;
  484. { we have at least two args }
  485. { with at max 2 colon_para in between }
  486. { string arg }
  487. hp:=node;
  488. node:=node^.right;
  489. hp^.right:=nil;
  490. dummycoll.paratyp:=vs_var;
  491. if is_shortstring(hp^.resulttype) then
  492. dummycoll.data:=openshortstringdef
  493. else
  494. dummycoll.data:=hp^.resulttype;
  495. procedureprefix:='FPC_'+pstringdef(hp^.resulttype)^.stringtypname+'_';
  496. secondcallparan(hp,@dummycoll,false,false,false,0);
  497. if codegenerror then
  498. exit;
  499. dummycoll.paratyp:=vs_const;
  500. disposetree(p^.left);
  501. p^.left:=nil;
  502. { second arg }
  503. hp:=node;
  504. node:=node^.right;
  505. hp^.right:=nil;
  506. { if real push real type }
  507. if is_real then
  508. push_int(ord(realtype));
  509. { frac para }
  510. if hp^.is_colon_para and assigned(node) and
  511. node^.is_colon_para then
  512. begin
  513. dummycoll.data:=hp^.resulttype;
  514. secondcallparan(hp,@dummycoll,false
  515. ,false,false,0
  516. );
  517. if codegenerror then
  518. exit;
  519. disposetree(hp);
  520. hp:=node;
  521. node:=node^.right;
  522. hp^.right:=nil;
  523. has_length:=true;
  524. end
  525. else
  526. if is_real then
  527. push_int(-1);
  528. { third arg, length only if is_real }
  529. if hp^.is_colon_para then
  530. begin
  531. dummycoll.data:=hp^.resulttype;
  532. secondcallparan(hp,@dummycoll,false
  533. ,false,false,0
  534. );
  535. if codegenerror then
  536. exit;
  537. disposetree(hp);
  538. hp:=node;
  539. node:=node^.right;
  540. hp^.right:=nil;
  541. end
  542. else
  543. if is_real then
  544. push_int(-32767)
  545. else
  546. push_int(-1);
  547. { Convert float to bestreal }
  548. if is_real then
  549. begin
  550. hp^.left:=gentypeconvnode(hp^.left,bestrealdef^);
  551. firstpass(hp^.left);
  552. end;
  553. { last arg longint or real }
  554. secondcallparan(hp,@dummycoll,false
  555. ,false,false,0
  556. );
  557. if codegenerror then
  558. exit;
  559. if is_real then
  560. emitcall(procedureprefix+'FLOAT')
  561. else
  562. case porddef(hp^.resulttype)^.typ of
  563. u32bit:
  564. emitcall(procedureprefix+'CARDINAL');
  565. u64bit:
  566. emitcall(procedureprefix+'QWORD');
  567. s64bit:
  568. emitcall(procedureprefix+'INT64');
  569. else
  570. emitcall(procedureprefix+'LONGINT');
  571. end;
  572. disposetree(hp);
  573. popusedregisters(pushed);
  574. end;
  575. Procedure Handle_Val;
  576. var
  577. hp,node, code_para, dest_para : ptree;
  578. hreg,hreg2: TRegister;
  579. hdef: POrdDef;
  580. procedureprefix : string;
  581. hr, hr2: TReference;
  582. dummycoll : tdefcoll;
  583. has_code, has_32bit_code, oldregisterdef: boolean;
  584. r : preference;
  585. begin
  586. dummycoll.register:=R_NO;
  587. node:=p^.left;
  588. hp:=node;
  589. node:=node^.right;
  590. hp^.right:=nil;
  591. {if we have 3 parameters, we have a code parameter}
  592. has_code := Assigned(node^.right);
  593. has_32bit_code := false;
  594. reset_reference(hr);
  595. hreg := R_NO;
  596. If has_code then
  597. Begin
  598. {code is an orddef, that's checked in tcinl}
  599. code_para := hp;
  600. hp := node;
  601. node := node^.right;
  602. hp^.right := nil;
  603. has_32bit_code := (porddef(code_para^.left^.resulttype)^.typ in [u32bit,s32bit]);
  604. End;
  605. {hp = destination now, save for later use}
  606. dest_para := hp;
  607. {if EAX is already in use, it's a register variable. Since we don't
  608. need another register besides EAX, release the one we got}
  609. If hreg <> R_EAX Then ungetregister32(hreg);
  610. {load and push the address of the destination}
  611. dummycoll.paratyp:=vs_var;
  612. dummycoll.data:=dest_para^.resulttype;
  613. secondcallparan(dest_para,@dummycoll,false,false,false,0);
  614. if codegenerror then
  615. exit;
  616. {save the regvars}
  617. pushusedregisters(pushed,$ff);
  618. {now that we've already pushed the addres of dest_para^.left on the
  619. stack, we can put the real parameters on the stack}
  620. If has_32bit_code Then
  621. Begin
  622. dummycoll.paratyp:=vs_var;
  623. dummycoll.data:=code_para^.resulttype;
  624. secondcallparan(code_para,@dummycoll,false,false,false,0);
  625. if codegenerror then
  626. exit;
  627. Disposetree(code_para);
  628. End
  629. Else
  630. Begin
  631. {only 32bit code parameter is supported, so fake one}
  632. GetTempOfSizeReference(4,hr);
  633. emitpushreferenceaddr(hr);
  634. End;
  635. {node = first parameter = string}
  636. dummycoll.paratyp:=vs_const;
  637. dummycoll.data:=node^.resulttype;
  638. secondcallparan(node,@dummycoll,false,false,false,0);
  639. if codegenerror then
  640. exit;
  641. Case dest_para^.resulttype^.deftype of
  642. floatdef:
  643. begin
  644. procedureprefix := 'FPC_VAL_REAL_';
  645. if pfloatdef(p^.resulttype)^.typ<>f32bit then
  646. inc(fpuvaroffset);
  647. end;
  648. orddef:
  649. if is_64bitint(dest_para^.resulttype) then
  650. begin
  651. if is_signed(dest_para^.resulttype) then
  652. procedureprefix := 'FPC_VAL_INT64_'
  653. else
  654. procedureprefix := 'FPC_VAL_QWORD_';
  655. end
  656. else
  657. begin
  658. if is_signed(dest_para^.resulttype) then
  659. begin
  660. {if we are converting to a signed number, we have to include the
  661. size of the destination, so the Val function can extend the sign
  662. of the result to allow proper range checking}
  663. emit_const(A_PUSH,S_L,dest_para^.resulttype^.size);
  664. procedureprefix := 'FPC_VAL_SINT_'
  665. end
  666. else
  667. procedureprefix := 'FPC_VAL_UINT_';
  668. end;
  669. End;
  670. emitcall(procedureprefix+pstringdef(node^.resulttype)^.stringtypname);
  671. { before disposing node we need to ungettemp !! PM }
  672. if node^.left^.location.loc in [LOC_REFERENCE,LOC_MEM] then
  673. ungetiftemp(node^.left^.location.reference);
  674. disposetree(node);
  675. p^.left := nil;
  676. {reload esi in case the dest_para/code_para is a class variable or so}
  677. maybe_loadesi;
  678. If (dest_para^.resulttype^.deftype = orddef) Then
  679. Begin
  680. {store the result in a safe place, because EAX may be used by a
  681. register variable}
  682. hreg := getexplicitregister32(R_EAX);
  683. emit_reg_reg(A_MOV,S_L,R_EAX,hreg);
  684. if is_64bitint(dest_para^.resulttype) then
  685. begin
  686. hreg2:=getexplicitregister32(R_EDX);
  687. emit_reg_reg(A_MOV,S_L,R_EDX,hreg2);
  688. end;
  689. {as of now, hreg now holds the location of the result, if it was
  690. integer}
  691. End;
  692. { restore the register vars}
  693. popusedregisters(pushed);
  694. If has_code and Not(has_32bit_code) Then
  695. {only 16bit code is possible}
  696. Begin
  697. {load the address of the code parameter}
  698. secondpass(code_para^.left);
  699. {move the code to its destination}
  700. emit_ref_reg(A_MOV,S_L,NewReference(hr),R_EDI);
  701. emit_mov_reg_loc(R_DI,code_para^.left^.location);
  702. Disposetree(code_para);
  703. End;
  704. {restore the address of the result}
  705. emit_reg(A_POP,S_L,R_EDI);
  706. {set up hr2 to a refernce with EDI as base register}
  707. reset_reference(hr2);
  708. hr2.base := R_EDI;
  709. {save the function result in the destination variable}
  710. Case dest_para^.left^.resulttype^.deftype of
  711. floatdef:
  712. floatstore(PFloatDef(dest_para^.left^.resulttype)^.typ, hr2);
  713. orddef:
  714. Case PordDef(dest_para^.left^.resulttype)^.typ of
  715. u8bit,s8bit:
  716. emit_reg_ref(A_MOV, S_B,
  717. RegToReg8(hreg),newreference(hr2));
  718. u16bit,s16bit:
  719. emit_reg_ref(A_MOV, S_W,
  720. RegToReg16(hreg),newreference(hr2));
  721. u32bit,s32bit:
  722. emit_reg_ref(A_MOV, S_L,
  723. hreg,newreference(hr2));
  724. u64bit,s64bit:
  725. begin
  726. emit_reg_ref(A_MOV, S_L,
  727. hreg,newreference(hr2));
  728. r:=newreference(hr2);
  729. inc(r^.offset,4);
  730. emit_reg_ref(A_MOV, S_L,
  731. hreg2,r);
  732. end;
  733. End;
  734. End;
  735. If (cs_check_range in aktlocalswitches) and
  736. (dest_para^.left^.resulttype^.deftype = orddef) and
  737. (not(is_64bitint(dest_para^.left^.resulttype))) and
  738. {the following has to be changed to 64bit checking, once Val
  739. returns 64 bit values (unless a special Val function is created
  740. for that)}
  741. {no need to rangecheck longints or cardinals on 32bit processors}
  742. not((porddef(dest_para^.left^.resulttype)^.typ = s32bit) and
  743. (porddef(dest_para^.left^.resulttype)^.low = $80000000) and
  744. (porddef(dest_para^.left^.resulttype)^.high = $7fffffff)) and
  745. not((porddef(dest_para^.left^.resulttype)^.typ = u32bit) and
  746. (porddef(dest_para^.left^.resulttype)^.low = 0) and
  747. (porddef(dest_para^.left^.resulttype)^.high = $ffffffff)) then
  748. Begin
  749. hp := getcopy(dest_para^.left);
  750. hp^.location.loc := LOC_REGISTER;
  751. hp^.location.register := hreg;
  752. {do not register this temporary def}
  753. OldRegisterDef := RegisterDef;
  754. RegisterDef := False;
  755. Case PordDef(dest_para^.left^.resulttype)^.typ of
  756. u8bit,u16bit,u32bit: new(hdef,init(u32bit,0,$ffffffff));
  757. s8bit,s16bit,s32bit: new(hdef,init(s32bit,$80000000,$7fffffff));
  758. end;
  759. hp^.resulttype := hdef;
  760. emitrangecheck(hp,dest_para^.left^.resulttype);
  761. hp^.right := nil;
  762. Dispose(hp^.resulttype, Done);
  763. RegisterDef := OldRegisterDef;
  764. disposetree(hp);
  765. End;
  766. {dest_para^.right is already nil}
  767. disposetree(dest_para);
  768. UnGetIfTemp(hr);
  769. end;
  770. var
  771. r : preference;
  772. hp : ptree;
  773. l : longint;
  774. ispushed : boolean;
  775. hregister : tregister;
  776. otlabel,oflabel : pasmlabel;
  777. oldpushedparasize : longint;
  778. begin
  779. { save & reset pushedparasize }
  780. oldpushedparasize:=pushedparasize;
  781. pushedparasize:=0;
  782. case p^.inlinenumber of
  783. in_assert_x_y:
  784. begin
  785. otlabel:=truelabel;
  786. oflabel:=falselabel;
  787. getlabel(truelabel);
  788. getlabel(falselabel);
  789. secondpass(p^.left^.left);
  790. if cs_do_assertion in aktlocalswitches then
  791. begin
  792. maketojumpbool(p^.left^.left);
  793. emitlab(falselabel);
  794. { erroraddr }
  795. emit_reg(A_PUSH,S_L,R_EBP);
  796. { lineno }
  797. emit_const(A_PUSH,S_L,aktfilepos.line);
  798. { filename string }
  799. hp:=genstringconstnode(current_module^.sourcefiles^.get_file_name(aktfilepos.fileindex));
  800. secondpass(hp);
  801. if codegenerror then
  802. exit;
  803. emitpushreferenceaddr(hp^.location.reference);
  804. disposetree(hp);
  805. { push msg }
  806. secondpass(p^.left^.right^.left);
  807. emitpushreferenceaddr(p^.left^.right^.left^.location.reference);
  808. { call }
  809. emitcall('FPC_ASSERT');
  810. emitlab(truelabel);
  811. end;
  812. freelabel(truelabel);
  813. freelabel(falselabel);
  814. truelabel:=otlabel;
  815. falselabel:=oflabel;
  816. end;
  817. in_lo_word,
  818. in_hi_word :
  819. begin
  820. secondpass(p^.left);
  821. p^.location.loc:=LOC_REGISTER;
  822. if p^.left^.location.loc<>LOC_REGISTER then
  823. begin
  824. if p^.left^.location.loc=LOC_CREGISTER then
  825. begin
  826. p^.location.register:=reg32toreg16(getregister32);
  827. emit_reg_reg(A_MOV,S_W,p^.left^.location.register,
  828. p^.location.register);
  829. end
  830. else
  831. begin
  832. del_reference(p^.left^.location.reference);
  833. p^.location.register:=reg32toreg16(getregister32);
  834. emit_ref_reg(A_MOV,S_W,newreference(p^.left^.location.reference),
  835. p^.location.register);
  836. end;
  837. end
  838. else p^.location.register:=p^.left^.location.register;
  839. if p^.inlinenumber=in_hi_word then
  840. emit_const_reg(A_SHR,S_W,8,p^.location.register);
  841. p^.location.register:=reg16toreg8(p^.location.register);
  842. end;
  843. in_sizeof_x,
  844. in_typeof_x :
  845. begin
  846. { for both cases load vmt }
  847. if p^.left^.treetype=typen then
  848. begin
  849. p^.location.register:=getregister32;
  850. emit_sym_ofs_reg(A_MOV,
  851. S_L,newasmsymbol(pobjectdef(p^.left^.resulttype)^.vmt_mangledname),0,
  852. p^.location.register);
  853. end
  854. else
  855. begin
  856. secondpass(p^.left);
  857. del_reference(p^.left^.location.reference);
  858. p^.location.loc:=LOC_REGISTER;
  859. p^.location.register:=getregister32;
  860. { load VMT pointer }
  861. inc(p^.left^.location.reference.offset,
  862. pobjectdef(p^.left^.resulttype)^.vmt_offset);
  863. emit_ref_reg(A_MOV,S_L,
  864. newreference(p^.left^.location.reference),
  865. p^.location.register);
  866. end;
  867. { in sizeof load size }
  868. if p^.inlinenumber=in_sizeof_x then
  869. begin
  870. new(r);
  871. reset_reference(r^);
  872. r^.base:=p^.location.register;
  873. emit_ref_reg(A_MOV,S_L,r,
  874. p^.location.register);
  875. end;
  876. end;
  877. in_lo_long,
  878. in_hi_long :
  879. begin
  880. secondpass(p^.left);
  881. p^.location.loc:=LOC_REGISTER;
  882. if p^.left^.location.loc<>LOC_REGISTER then
  883. begin
  884. if p^.left^.location.loc=LOC_CREGISTER then
  885. begin
  886. p^.location.register:=getregister32;
  887. emit_reg_reg(A_MOV,S_L,p^.left^.location.register,
  888. p^.location.register);
  889. end
  890. else
  891. begin
  892. del_reference(p^.left^.location.reference);
  893. p^.location.register:=getregister32;
  894. emit_ref_reg(A_MOV,S_L,newreference(p^.left^.location.reference),
  895. p^.location.register);
  896. end;
  897. end
  898. else p^.location.register:=p^.left^.location.register;
  899. if p^.inlinenumber=in_hi_long then
  900. emit_const_reg(A_SHR,S_L,16,p^.location.register);
  901. p^.location.register:=reg32toreg16(p^.location.register);
  902. end;
  903. in_lo_qword,
  904. in_hi_qword:
  905. begin
  906. secondpass(p^.left);
  907. p^.location.loc:=LOC_REGISTER;
  908. case p^.left^.location.loc of
  909. LOC_CREGISTER:
  910. begin
  911. p^.location.register:=getregister32;
  912. if p^.inlinenumber=in_hi_qword then
  913. emit_reg_reg(A_MOV,S_L,p^.left^.location.registerhigh,
  914. p^.location.register)
  915. else
  916. emit_reg_reg(A_MOV,S_L,p^.left^.location.registerlow,
  917. p^.location.register)
  918. end;
  919. LOC_MEM,LOC_REFERENCE:
  920. begin
  921. del_reference(p^.left^.location.reference);
  922. p^.location.register:=getregister32;
  923. r:=newreference(p^.left^.location.reference);
  924. if p^.inlinenumber=in_hi_qword then
  925. inc(r^.offset,4);
  926. emit_ref_reg(A_MOV,S_L,
  927. r,p^.location.register);
  928. end;
  929. LOC_REGISTER:
  930. begin
  931. if p^.inlinenumber=in_hi_qword then
  932. begin
  933. p^.location.register:=p^.left^.location.registerhigh;
  934. ungetregister32(p^.left^.location.registerlow);
  935. end
  936. else
  937. begin
  938. p^.location.register:=p^.left^.location.registerlow;
  939. ungetregister32(p^.left^.location.registerhigh);
  940. end;
  941. end;
  942. end;
  943. end;
  944. in_length_string :
  945. begin
  946. secondpass(p^.left);
  947. set_location(p^.location,p^.left^.location);
  948. { length in ansi strings is at offset -8 }
  949. if is_ansistring(p^.left^.resulttype) then
  950. dec(p^.location.reference.offset,8)
  951. { char is always 1, so make it a constant value }
  952. else if is_char(p^.left^.resulttype) then
  953. begin
  954. clear_location(p^.location);
  955. p^.location.loc:=LOC_MEM;
  956. p^.location.reference.is_immediate:=true;
  957. p^.location.reference.offset:=1;
  958. end;
  959. end;
  960. in_pred_x,
  961. in_succ_x:
  962. begin
  963. secondpass(p^.left);
  964. if not (cs_check_overflow in aktlocalswitches) then
  965. if p^.inlinenumber=in_pred_x then
  966. asmop:=A_DEC
  967. else
  968. asmop:=A_INC
  969. else
  970. if p^.inlinenumber=in_pred_x then
  971. asmop:=A_SUB
  972. else
  973. asmop:=A_ADD;
  974. case p^.resulttype^.size of
  975. 4 : opsize:=S_L;
  976. 2 : opsize:=S_W;
  977. 1 : opsize:=S_B;
  978. else
  979. internalerror(10080);
  980. end;
  981. p^.location.loc:=LOC_REGISTER;
  982. if p^.left^.location.loc<>LOC_REGISTER then
  983. begin
  984. p^.location.register:=getregister32;
  985. if (p^.resulttype^.size=2) then
  986. p^.location.register:=reg32toreg16(p^.location.register);
  987. if (p^.resulttype^.size=1) then
  988. p^.location.register:=reg32toreg8(p^.location.register);
  989. if p^.left^.location.loc=LOC_CREGISTER then
  990. emit_reg_reg(A_MOV,opsize,p^.left^.location.register,
  991. p^.location.register)
  992. else
  993. if p^.left^.location.loc=LOC_FLAGS then
  994. emit_flag2reg(p^.left^.location.resflags,p^.location.register)
  995. else
  996. begin
  997. del_reference(p^.left^.location.reference);
  998. emit_ref_reg(A_MOV,opsize,newreference(p^.left^.location.reference),
  999. p^.location.register);
  1000. end;
  1001. end
  1002. else p^.location.register:=p^.left^.location.register;
  1003. if not (cs_check_overflow in aktlocalswitches) then
  1004. emit_reg(asmop,opsize,
  1005. p^.location.register)
  1006. else
  1007. emit_const_reg(asmop,opsize,1,
  1008. p^.location.register);
  1009. emitoverflowcheck(p);
  1010. emitrangecheck(p,p^.resulttype);
  1011. end;
  1012. in_dec_x,
  1013. in_inc_x :
  1014. begin
  1015. { set defaults }
  1016. addvalue:=1;
  1017. addconstant:=true;
  1018. { load first parameter, must be a reference }
  1019. secondpass(p^.left^.left);
  1020. case p^.left^.left^.resulttype^.deftype of
  1021. orddef,
  1022. enumdef : begin
  1023. case p^.left^.left^.resulttype^.size of
  1024. 1 : opsize:=S_B;
  1025. 2 : opsize:=S_W;
  1026. 4 : opsize:=S_L;
  1027. end;
  1028. end;
  1029. pointerdef : begin
  1030. opsize:=S_L;
  1031. if porddef(ppointerdef(p^.left^.left^.resulttype)^.definition)=voiddef then
  1032. addvalue:=1
  1033. else
  1034. addvalue:=ppointerdef(p^.left^.left^.resulttype)^.definition^.size;
  1035. end;
  1036. else
  1037. internalerror(10081);
  1038. end;
  1039. { second argument specified?, must be a s32bit in register }
  1040. if assigned(p^.left^.right) then
  1041. begin
  1042. secondpass(p^.left^.right^.left);
  1043. { when constant, just multiply the addvalue }
  1044. if is_constintnode(p^.left^.right^.left) then
  1045. addvalue:=addvalue*get_ordinal_value(p^.left^.right^.left)
  1046. else
  1047. begin
  1048. case p^.left^.right^.left^.location.loc of
  1049. LOC_REGISTER,
  1050. LOC_CREGISTER : hregister:=p^.left^.right^.left^.location.register;
  1051. LOC_MEM,
  1052. LOC_REFERENCE : begin
  1053. del_reference(p^.left^.right^.left^.location.reference);
  1054. hregister:=getregister32;
  1055. emit_ref_reg(A_MOV,S_L,
  1056. newreference(p^.left^.right^.left^.location.reference),hregister);
  1057. end;
  1058. else
  1059. internalerror(10082);
  1060. end;
  1061. { insert multiply with addvalue if its >1 }
  1062. if addvalue>1 then
  1063. emit_const_reg(A_IMUL,opsize,
  1064. addvalue,hregister);
  1065. addconstant:=false;
  1066. end;
  1067. end;
  1068. { write the add instruction }
  1069. if addconstant then
  1070. begin
  1071. if (addvalue=1) and not(cs_check_overflow in aktlocalswitches) then
  1072. begin
  1073. if p^.left^.left^.location.loc=LOC_CREGISTER then
  1074. emit_reg(incdecop[p^.inlinenumber],opsize,
  1075. p^.left^.left^.location.register)
  1076. else
  1077. emit_ref(incdecop[p^.inlinenumber],opsize,
  1078. newreference(p^.left^.left^.location.reference))
  1079. end
  1080. else
  1081. begin
  1082. if p^.left^.left^.location.loc=LOC_CREGISTER then
  1083. emit_const_reg(addsubop[p^.inlinenumber],opsize,
  1084. addvalue,p^.left^.left^.location.register)
  1085. else
  1086. emit_const_ref(addsubop[p^.inlinenumber],opsize,
  1087. addvalue,newreference(p^.left^.left^.location.reference));
  1088. end
  1089. end
  1090. else
  1091. begin
  1092. { BUG HERE : detected with nasm :
  1093. hregister is allways 32 bit
  1094. it should be converted to 16 or 8 bit depending on op_size PM }
  1095. { still not perfect :
  1096. if hregister is already a 16 bit reg ?? PM }
  1097. { makeregXX is the solution (FK) }
  1098. case opsize of
  1099. S_B : hregister:=makereg8(hregister);
  1100. S_W : hregister:=makereg16(hregister);
  1101. end;
  1102. if p^.left^.left^.location.loc=LOC_CREGISTER then
  1103. emit_reg_reg(addsubop[p^.inlinenumber],opsize,
  1104. hregister,p^.left^.left^.location.register)
  1105. else
  1106. emit_reg_ref(addsubop[p^.inlinenumber],opsize,
  1107. hregister,newreference(p^.left^.left^.location.reference));
  1108. case opsize of
  1109. S_B : hregister:=reg8toreg32(hregister);
  1110. S_W : hregister:=reg16toreg32(hregister);
  1111. end;
  1112. ungetregister32(hregister);
  1113. end;
  1114. emitoverflowcheck(p^.left^.left);
  1115. emitrangecheck(p^.left^.left,p^.left^.left^.resulttype);
  1116. end;
  1117. in_assigned_x :
  1118. begin
  1119. secondpass(p^.left^.left);
  1120. p^.location.loc:=LOC_FLAGS;
  1121. if (p^.left^.left^.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
  1122. begin
  1123. emit_reg_reg(A_OR,S_L,
  1124. p^.left^.left^.location.register,
  1125. p^.left^.left^.location.register);
  1126. ungetregister32(p^.left^.left^.location.register);
  1127. end
  1128. else
  1129. begin
  1130. emit_const_ref(A_CMP,S_L,0,
  1131. newreference(p^.left^.left^.location.reference));
  1132. del_reference(p^.left^.left^.location.reference);
  1133. end;
  1134. p^.location.resflags:=F_NE;
  1135. end;
  1136. in_reset_typedfile,in_rewrite_typedfile :
  1137. begin
  1138. pushusedregisters(pushed,$ff);
  1139. emit_const(A_PUSH,S_L,pfiledef(p^.left^.resulttype)^.typed_as^.size);
  1140. secondpass(p^.left);
  1141. emitpushreferenceaddr(p^.left^.location.reference);
  1142. if p^.inlinenumber=in_reset_typedfile then
  1143. emitcall('FPC_RESET_TYPED')
  1144. else
  1145. emitcall('FPC_REWRITE_TYPED');
  1146. popusedregisters(pushed);
  1147. end;
  1148. in_write_x :
  1149. handlereadwrite(false,false);
  1150. in_writeln_x :
  1151. handlereadwrite(false,true);
  1152. in_read_x :
  1153. handlereadwrite(true,false);
  1154. in_readln_x :
  1155. handlereadwrite(true,true);
  1156. in_str_x_string :
  1157. begin
  1158. handle_str;
  1159. maybe_loadesi;
  1160. end;
  1161. in_val_x :
  1162. Begin
  1163. handle_val;
  1164. End;
  1165. in_include_x_y,
  1166. in_exclude_x_y:
  1167. begin
  1168. secondpass(p^.left^.left);
  1169. if p^.left^.right^.left^.treetype=ordconstn then
  1170. begin
  1171. { calculate bit position }
  1172. l:=1 shl (p^.left^.right^.left^.value mod 32);
  1173. { determine operator }
  1174. if p^.inlinenumber=in_include_x_y then
  1175. asmop:=A_OR
  1176. else
  1177. begin
  1178. asmop:=A_AND;
  1179. l:=not(l);
  1180. end;
  1181. if (p^.left^.left^.location.loc=LOC_REFERENCE) then
  1182. begin
  1183. inc(p^.left^.left^.location.reference.offset,(p^.left^.right^.left^.value div 32)*4);
  1184. emit_const_ref(asmop,S_L,
  1185. l,newreference(p^.left^.left^.location.reference));
  1186. del_reference(p^.left^.left^.location.reference);
  1187. end
  1188. else
  1189. { LOC_CREGISTER }
  1190. emit_const_reg(asmop,S_L,
  1191. l,p^.left^.left^.location.register);
  1192. end
  1193. else
  1194. begin
  1195. { generate code for the element to set }
  1196. ispushed:=maybe_push(p^.left^.right^.left^.registers32,p^.left^.left,false);
  1197. secondpass(p^.left^.right^.left);
  1198. if ispushed then
  1199. restore(p^.left^.left,false);
  1200. { determine asm operator }
  1201. if p^.inlinenumber=in_include_x_y then
  1202. asmop:=A_BTS
  1203. else
  1204. asmop:=A_BTR;
  1205. if psetdef(p^.left^.resulttype)^.settype=smallset then
  1206. begin
  1207. if p^.left^.right^.left^.location.loc in [LOC_CREGISTER,LOC_REGISTER] then
  1208. hregister:=p^.left^.right^.left^.location.register
  1209. else
  1210. begin
  1211. hregister:=R_EDI;
  1212. opsize:=def2def_opsize(p^.left^.right^.left^.resulttype,u32bitdef);
  1213. if opsize in [S_B,S_W,S_L] then
  1214. op:=A_MOV
  1215. else
  1216. op:=A_MOVZX;
  1217. emit_ref_reg(op,opsize,
  1218. newreference(p^.left^.right^.left^.location.reference),R_EDI);
  1219. end;
  1220. if (p^.left^.left^.location.loc=LOC_REFERENCE) then
  1221. emit_reg_ref(asmop,S_L,hregister,
  1222. newreference(p^.left^.left^.location.reference))
  1223. else
  1224. emit_reg_reg(asmop,S_L,hregister,
  1225. p^.left^.left^.location.register);
  1226. end
  1227. else
  1228. begin
  1229. pushsetelement(p^.left^.right^.left);
  1230. { normset is allways a ref }
  1231. emitpushreferenceaddr(p^.left^.left^.location.reference);
  1232. if p^.inlinenumber=in_include_x_y then
  1233. emitcall('FPC_SET_SET_BYTE')
  1234. else
  1235. emitcall('FPC_SET_UNSET_BYTE');
  1236. {CGMessage(cg_e_include_not_implemented);}
  1237. end;
  1238. end;
  1239. end;
  1240. {$ifdef SUPPORT_MMX}
  1241. in_mmx_pcmpeqb..in_mmx_pcmpgtw:
  1242. begin
  1243. if p^.left^.location.loc=LOC_REGISTER then
  1244. begin
  1245. {!!!!!!!}
  1246. end
  1247. else if p^.left^.left^.location.loc=LOC_REGISTER then
  1248. begin
  1249. {!!!!!!!}
  1250. end
  1251. else
  1252. begin
  1253. {!!!!!!!}
  1254. end;
  1255. end;
  1256. {$endif SUPPORT_MMX}
  1257. else internalerror(9);
  1258. end;
  1259. { reset pushedparasize }
  1260. pushedparasize:=oldpushedparasize;
  1261. end;
  1262. end.
  1263. {
  1264. $Log$
  1265. Revision 1.69 1999-08-28 15:34:16 florian
  1266. * bug 519 fixed
  1267. Revision 1.68 1999/08/19 13:08:47 pierre
  1268. * emit_??? used
  1269. Revision 1.67 1999/08/10 13:21:08 pierre
  1270. * fpuvaroffset not increased for f32bit float type
  1271. Revision 1.66 1999/08/10 12:47:53 pierre
  1272. * fpuvaroffset problems solved
  1273. Revision 1.65 1999/08/04 00:22:47 florian
  1274. * renamed i386asm and i386base to cpuasm and cpubase
  1275. Revision 1.64 1999/08/03 22:02:42 peter
  1276. * moved bitmask constants to sets
  1277. * some other type/const renamings
  1278. Revision 1.63 1999/07/23 16:05:18 peter
  1279. * alignment is now saved in the symtable
  1280. * C alignment added for records
  1281. * PPU version increased to solve .12 <-> .13 probs
  1282. Revision 1.62 1999/07/05 20:13:10 peter
  1283. * removed temp defines
  1284. Revision 1.61 1999/07/03 14:14:27 florian
  1285. + start of val(int64/qword)
  1286. * longbool, wordbool constants weren't written, fixed
  1287. Revision 1.60 1999/07/01 15:49:09 florian
  1288. * int64/qword type release
  1289. + lo/hi for int64/qword
  1290. Revision 1.59 1999/06/21 16:33:27 jonas
  1291. * fixed include() with smallsets
  1292. Revision 1.58 1999/06/11 11:44:56 peter
  1293. *** empty log message ***
  1294. Revision 1.57 1999/06/02 10:11:43 florian
  1295. * make cycle fixed i.e. compilation with 0.99.10
  1296. * some fixes for qword
  1297. * start of register calling conventions
  1298. Revision 1.56 1999/05/31 12:43:32 peter
  1299. * fixed register allocation for storefuncresult
  1300. Revision 1.55 1999/05/27 19:44:13 peter
  1301. * removed oldasm
  1302. * plabel -> pasmlabel
  1303. * -a switches to source writing automaticly
  1304. * assembler readers OOPed
  1305. * asmsymbol automaticly external
  1306. * jumptables and other label fixes for asm readers
  1307. Revision 1.54 1999/05/23 19:55:11 florian
  1308. * qword/int64 multiplication fixed
  1309. + qword/int64 subtraction
  1310. Revision 1.53 1999/05/23 18:42:01 florian
  1311. * better error recovering in typed constants
  1312. * some problems with arrays of const fixed, some problems
  1313. due my previous
  1314. - the location type of array constructor is now LOC_MEM
  1315. - the pushing of high fixed
  1316. - parameter copying fixed
  1317. - zero temp. allocation removed
  1318. * small problem in the assembler writers fixed:
  1319. ref to nil wasn't written correctly
  1320. Revision 1.52 1999/05/21 13:54:50 peter
  1321. * NEWLAB for label as symbol
  1322. Revision 1.51 1999/05/18 21:58:27 florian
  1323. * fixed some bugs related to temp. ansistrings and functions results
  1324. which return records/objects/arrays which need init/final.
  1325. Revision 1.50 1999/05/17 21:57:03 florian
  1326. * new temporary ansistring handling
  1327. Revision 1.49 1999/05/12 15:46:26 pierre
  1328. * handle_str disposetree was badly placed
  1329. Revision 1.48 1999/05/12 00:19:42 peter
  1330. * removed R_DEFAULT_SEG
  1331. * uniform float names
  1332. Revision 1.47 1999/05/06 09:05:13 peter
  1333. * generic write_float and str_float
  1334. * fixed constant float conversions
  1335. Revision 1.46 1999/05/05 16:18:20 jonas
  1336. * changes to handle_val so register vars are pushed/poped only once
  1337. Revision 1.45 1999/05/01 13:24:08 peter
  1338. * merged nasm compiler
  1339. * old asm moved to oldasm/
  1340. Revision 1.44 1999/04/26 18:28:13 peter
  1341. * better read/write array
  1342. Revision 1.43 1999/04/19 09:45:48 pierre
  1343. + cdecl or stdcall push all args with longint size
  1344. * tempansi stuff cleaned up
  1345. Revision 1.42 1999/04/14 09:11:59 peter
  1346. * fixed include
  1347. Revision 1.41 1999/04/08 23:59:49 pierre
  1348. * temp string for val code freed
  1349. Revision 1.40 1999/04/08 15:57:46 peter
  1350. + subrange checking for readln()
  1351. Revision 1.39 1999/04/07 15:31:16 pierre
  1352. * all formaldefs are now a sinlge definition
  1353. cformaldef (this was necessary for double_checksum)
  1354. + small part of double_checksum code
  1355. Revision 1.38 1999/04/05 11:07:26 jonas
  1356. * fixed some typos in the constants of the range checking for Val
  1357. Revision 1.37 1999/04/01 22:07:51 peter
  1358. * universal string names (ansistr instead of stransi) for val/str
  1359. Revision 1.36 1999/04/01 06:21:04 jonas
  1360. * added initialization for has_32bit_code (caused problems with Val statement
  1361. without code parameter)
  1362. Revision 1.35 1999/03/31 20:30:49 michael
  1363. * fixed typo: odlval to oldval
  1364. Revision 1.34 1999/03/31 17:13:09 jonas
  1365. * bugfix for -Ox with internal val code
  1366. * internal val code now requires less free registers
  1367. * internal val code no longer needs a temp var for range checking
  1368. Revision 1.33 1999/03/26 00:24:15 peter
  1369. * last para changed to long for easier pushing with 4 byte aligns
  1370. Revision 1.32 1999/03/26 00:05:26 peter
  1371. * released valintern
  1372. + deffile is now removed when compiling is finished
  1373. * ^( compiles now correct
  1374. + static directive
  1375. * shrd fixed
  1376. Revision 1.31 1999/03/24 23:16:49 peter
  1377. * fixed bugs 212,222,225,227,229,231,233
  1378. Revision 1.30 1999/03/16 17:52:56 jonas
  1379. * changes for internal Val code (do a "make cycle OPT=-dvalintern" to test)
  1380. * in cgi386inl: also range checking for subrange types (compile with "-dreadrangecheck")
  1381. * in cgai386: also small fixes to emitrangecheck
  1382. Revision 1.29 1999/02/25 21:02:27 peter
  1383. * ag386bin updates
  1384. + coff writer
  1385. Revision 1.28 1999/02/22 02:15:11 peter
  1386. * updates for ag386bin
  1387. Revision 1.27 1999/02/17 14:21:40 pierre
  1388. * unused local removed
  1389. Revision 1.26 1999/02/15 11:40:21 pierre
  1390. * pred/succ with overflow check must use ADD DEC !!
  1391. Revision 1.25 1999/02/05 10:56:19 florian
  1392. * in some cases a writeln of temp. ansistrings cause a memory leak, fixed
  1393. Revision 1.24 1999/01/21 22:10:39 peter
  1394. * fixed array of const
  1395. * generic platform independent high() support
  1396. Revision 1.23 1999/01/06 12:23:29 florian
  1397. * str(...) for ansi/long and widestrings fixed
  1398. Revision 1.22 1998/12/11 23:36:07 florian
  1399. + again more stuff for int64/qword:
  1400. - comparision operators
  1401. - code generation for: str, read(ln), write(ln)
  1402. Revision 1.21 1998/12/11 00:02:50 peter
  1403. + globtype,tokens,version unit splitted from globals
  1404. Revision 1.20 1998/11/27 14:50:32 peter
  1405. + open strings, $P switch support
  1406. Revision 1.19 1998/11/26 13:10:40 peter
  1407. * new int - int conversion -dNEWCNV
  1408. * some function renamings
  1409. Revision 1.18 1998/11/24 17:04:27 peter
  1410. * fixed length(char) when char is a variable
  1411. Revision 1.17 1998/11/05 12:02:33 peter
  1412. * released useansistring
  1413. * removed -Sv, its now available in fpc modes
  1414. Revision 1.16 1998/10/22 17:11:13 pierre
  1415. + terminated the include exclude implementation for i386
  1416. * enums inside records fixed
  1417. Revision 1.15 1998/10/21 15:12:50 pierre
  1418. * bug fix for IOCHECK inside a procedure with iocheck modifier
  1419. * removed the GPF for unexistant overloading
  1420. (firstcall was called with procedinition=nil !)
  1421. * changed typen to what Florian proposed
  1422. gentypenode(p : pdef) sets the typenodetype field
  1423. and resulttype is only set if inside bt_type block !
  1424. Revision 1.14 1998/10/20 08:06:40 pierre
  1425. * several memory corruptions due to double freemem solved
  1426. => never use p^.loc.location:=p^.left^.loc.location;
  1427. + finally I added now by default
  1428. that ra386dir translates global and unit symbols
  1429. + added a first field in tsymtable and
  1430. a nextsym field in tsym
  1431. (this allows to obtain ordered type info for
  1432. records and objects in gdb !)
  1433. Revision 1.13 1998/10/13 16:50:02 pierre
  1434. * undid some changes of Peter that made the compiler wrong
  1435. for m68k (I had to reinsert some ifdefs)
  1436. * removed several memory leaks under m68k
  1437. * removed the meory leaks for assembler readers
  1438. * cross compiling shoud work again better
  1439. ( crosscompiling sysamiga works
  1440. but as68k still complain about some code !)
  1441. Revision 1.12 1998/10/08 17:17:12 pierre
  1442. * current_module old scanner tagged as invalid if unit is recompiled
  1443. + added ppheap for better info on tracegetmem of heaptrc
  1444. (adds line column and file index)
  1445. * several memory leaks removed ith help of heaptrc !!
  1446. Revision 1.11 1998/10/05 21:33:15 peter
  1447. * fixed 161,165,166,167,168
  1448. Revision 1.10 1998/10/05 12:32:44 peter
  1449. + assert() support
  1450. Revision 1.8 1998/10/02 10:35:09 peter
  1451. * support for inc(pointer,value) which now increases with value instead
  1452. of 0*value :)
  1453. Revision 1.7 1998/09/21 08:45:07 pierre
  1454. + added vmt_offset in tobjectdef.write for fututre use
  1455. (first steps to have objects without vmt if no virtual !!)
  1456. + added fpu_used field for tabstractprocdef :
  1457. sets this level to 2 if the functions return with value in FPU
  1458. (is then set to correct value at parsing of implementation)
  1459. THIS MIGHT refuse some code with FPU expression too complex
  1460. that were accepted before and even in some cases
  1461. that don't overflow in fact
  1462. ( like if f : float; is a forward that finally in implementation
  1463. only uses one fpu register !!)
  1464. Nevertheless I think that it will improve security on
  1465. FPU operations !!
  1466. * most other changes only for UseBrowser code
  1467. (added symtable references for record and objects)
  1468. local switch for refs to args and local of each function
  1469. (static symtable still missing)
  1470. UseBrowser still not stable and probably broken by
  1471. the definition hash array !!
  1472. Revision 1.6 1998/09/20 12:26:37 peter
  1473. * merged fixes
  1474. Revision 1.5 1998/09/17 09:42:15 peter
  1475. + pass_2 for cg386
  1476. * Message() -> CGMessage() for pass_1/pass_2
  1477. Revision 1.4 1998/09/14 10:43:49 peter
  1478. * all internal RTL functions start with FPC_
  1479. Revision 1.3.2.1 1998/09/20 12:20:07 peter
  1480. * Fixed stack not on 4 byte boundary when doing a call
  1481. Revision 1.3 1998/09/05 23:03:57 florian
  1482. * some fixes to get -Or work:
  1483. - inc/dec didn't take care of CREGISTER
  1484. - register calculcation of inc/dec was wrong
  1485. - var/const parameters get now assigned 32 bit register, but
  1486. const parameters only if they are passed by reference !
  1487. Revision 1.2 1998/09/04 08:41:40 peter
  1488. * updated some error CGMessages
  1489. Revision 1.1 1998/08/31 12:22:14 peter
  1490. * secondinline moved to cg386inl
  1491. Revision 1.19 1998/08/31 08:52:03 peter
  1492. * fixed error 10 with succ() and pref()
  1493. Revision 1.18 1998/08/20 21:36:38 peter
  1494. * fixed 'with object do' bug
  1495. Revision 1.17 1998/08/19 16:07:36 jonas
  1496. * changed optimizer switches + cleanup of DestroyRefs in daopt386.pas
  1497. Revision 1.16 1998/08/18 09:24:36 pierre
  1498. * small warning position bug fixed
  1499. * support_mmx switches splitting was missing
  1500. * rhide error and warning output corrected
  1501. Revision 1.15 1998/08/13 11:00:09 peter
  1502. * fixed procedure<>procedure construct
  1503. Revision 1.14 1998/08/11 14:05:33 peter
  1504. * fixed sizeof(array of char)
  1505. Revision 1.13 1998/08/10 14:49:45 peter
  1506. + localswitches, moduleswitches, globalswitches splitting
  1507. Revision 1.12 1998/07/30 13:30:31 florian
  1508. * final implemenation of exception support, maybe it needs
  1509. some fixes :)
  1510. Revision 1.11 1998/07/24 22:16:52 florian
  1511. * internal error 10 together with array access fixed. I hope
  1512. that's the final fix.
  1513. Revision 1.10 1998/07/18 22:54:23 florian
  1514. * some ansi/wide/longstring support fixed:
  1515. o parameter passing
  1516. o returning as result from functions
  1517. Revision 1.9 1998/07/07 17:40:37 peter
  1518. * packrecords 4 works
  1519. * word aligning of parameters
  1520. Revision 1.8 1998/07/06 15:51:15 michael
  1521. Added length checking for string reading
  1522. Revision 1.7 1998/07/06 14:19:51 michael
  1523. + Added calls for reading/writing ansistrings
  1524. Revision 1.6 1998/07/01 15:28:48 peter
  1525. + better writeln/readln handling, now 100% like tp7
  1526. Revision 1.5 1998/06/25 14:04:17 peter
  1527. + internal inc/dec
  1528. Revision 1.4 1998/06/25 08:48:06 florian
  1529. * first version of rtti support
  1530. Revision 1.3 1998/06/09 16:01:33 pierre
  1531. + added procedure directive parsing for procvars
  1532. (accepted are popstack cdecl and pascal)
  1533. + added C vars with the following syntax
  1534. var C calias 'true_c_name';(can be followed by external)
  1535. reason is that you must add the Cprefix
  1536. which is target dependent
  1537. Revision 1.2 1998/06/08 13:13:29 pierre
  1538. + temporary variables now in temp_gen.pas unit
  1539. because it is processor independent
  1540. * mppc68k.bat modified to undefine i386 and support_mmx
  1541. (which are defaults for i386)
  1542. Revision 1.1 1998/06/05 17:44:10 peter
  1543. * splitted cgi386
  1544. }