cg386inl.pas 62 KB

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