cg386inl.pas 71 KB

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