cg386inl.pas 64 KB

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