n386cnv.pas 48 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 by Florian Klaempfl
  4. Generate i386 assembler for type converting 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 n386cnv;
  19. {$i defines.inc}
  20. interface
  21. uses
  22. node,ncnv,types;
  23. type
  24. ti386typeconvnode = class(ttypeconvnode)
  25. procedure second_int_to_int;virtual;
  26. procedure second_string_to_string;virtual;
  27. procedure second_cstring_to_pchar;virtual;
  28. procedure second_string_to_chararray;virtual;
  29. procedure second_array_to_pointer;virtual;
  30. procedure second_pointer_to_array;virtual;
  31. procedure second_chararray_to_string;virtual;
  32. procedure second_char_to_string;virtual;
  33. procedure second_int_to_real;virtual;
  34. procedure second_real_to_real;virtual;
  35. procedure second_cord_to_pointer;virtual;
  36. procedure second_proc_to_procvar;virtual;
  37. procedure second_bool_to_int;virtual;
  38. procedure second_int_to_bool;virtual;
  39. procedure second_load_smallset;virtual;
  40. procedure second_ansistring_to_pchar;virtual;
  41. procedure second_pchar_to_string;virtual;
  42. procedure second_class_to_intf;virtual;
  43. procedure second_nothing;virtual;
  44. procedure pass_2;override;
  45. procedure second_call_helper(c : tconverttype);
  46. end;
  47. ti386asnode = class(tasnode)
  48. procedure pass_2;override;
  49. end;
  50. ti386isnode = class(tisnode)
  51. procedure pass_2;override;
  52. end;
  53. implementation
  54. uses
  55. verbose,globals,systems,
  56. symconst,symdef,aasm,
  57. hcodegen,temp_gen,pass_2,
  58. ncon,ncal,
  59. cpubase,cpuasm,
  60. cgai386,tgcpu,n386util;
  61. {*****************************************************************************
  62. SecondTypeConv
  63. *****************************************************************************}
  64. procedure ti386typeconvnode.second_int_to_int;
  65. var
  66. op : tasmop;
  67. opsize : topsize;
  68. hregister,
  69. hregister2 : tregister;
  70. l : tasmlabel;
  71. begin
  72. { insert range check if not explicit conversion }
  73. if not(nf_explizit in flags) then
  74. emitrangecheck(left,resulttype.def);
  75. { is the result size smaller ? }
  76. if resulttype.def.size<left.resulttype.def.size then
  77. begin
  78. { only need to set the new size of a register }
  79. if (left.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
  80. begin
  81. case resulttype.def.size of
  82. 1 : location.register:=makereg8(left.location.register);
  83. 2 : location.register:=makereg16(left.location.register);
  84. 4 : location.register:=makereg32(left.location.register);
  85. end;
  86. { we can release the upper register }
  87. if is_64bitint(left.resulttype.def) then
  88. ungetregister32(left.location.registerhigh);
  89. end;
  90. end
  91. { is the result size bigger ? }
  92. else if resulttype.def.size>left.resulttype.def.size then
  93. begin
  94. { remove reference }
  95. if not(left.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
  96. begin
  97. del_reference(left.location.reference);
  98. { we can do this here as we need no temp inside }
  99. ungetiftemp(left.location.reference);
  100. end;
  101. { get op and opsize, handle separate for constants, because
  102. movz doesn't support constant values }
  103. if (left.location.loc=LOC_MEM) and (left.location.reference.is_immediate) then
  104. begin
  105. if is_64bitint(resulttype.def) then
  106. opsize:=S_L
  107. else
  108. opsize:=def_opsize(resulttype.def);
  109. op:=A_MOV;
  110. end
  111. else
  112. begin
  113. opsize:=def2def_opsize(left.resulttype.def,resulttype.def);
  114. if opsize in [S_B,S_W,S_L] then
  115. op:=A_MOV
  116. else
  117. if is_signed(left.resulttype.def) then
  118. op:=A_MOVSX
  119. else
  120. op:=A_MOVZX;
  121. end;
  122. { load the register we need }
  123. if left.location.loc<>LOC_REGISTER then
  124. hregister:=getregister32
  125. else
  126. hregister:=left.location.register;
  127. { set the correct register size and location }
  128. clear_location(location);
  129. location.loc:=LOC_REGISTER;
  130. { do we need a second register for a 64 bit type ? }
  131. if is_64bitint(resulttype.def) then
  132. begin
  133. hregister2:=getregister32;
  134. location.registerhigh:=hregister2;
  135. end;
  136. case resulttype.def.size of
  137. 1:
  138. location.register:=makereg8(hregister);
  139. 2:
  140. location.register:=makereg16(hregister);
  141. 4,8:
  142. location.register:=makereg32(hregister);
  143. end;
  144. { insert the assembler code }
  145. if left.location.loc in [LOC_CREGISTER,LOC_REGISTER] then
  146. emit_reg_reg(op,opsize,left.location.register,location.register)
  147. else
  148. emit_ref_reg(op,opsize,
  149. newreference(left.location.reference),location.register);
  150. { do we need a sign extension for int64? }
  151. if is_64bitint(resulttype.def) then
  152. { special case for constants (JM) }
  153. if is_constintnode(left) then
  154. begin
  155. if tordconstnode(left).value >= 0 then
  156. emit_reg_reg(A_XOR,S_L,
  157. hregister2,hregister2)
  158. else
  159. emit_const_reg(A_MOV,S_L,longint($ffffffff),hregister2);
  160. end
  161. else
  162. begin
  163. emit_reg_reg(A_XOR,S_L,
  164. hregister2,hregister2);
  165. if (torddef(resulttype.def).typ=s64bit) and
  166. is_signed(left.resulttype.def) then
  167. begin
  168. getlabel(l);
  169. emit_const_reg(A_TEST,S_L,longint($80000000),makereg32(hregister));
  170. emitjmp(C_Z,l);
  171. emit_reg(A_NOT,S_L,
  172. hregister2);
  173. emitlab(l);
  174. end;
  175. end;
  176. end;
  177. end;
  178. procedure ti386typeconvnode.second_string_to_string;
  179. var
  180. pushed : tpushed;
  181. regs_to_push: byte;
  182. begin
  183. { does anybody know a better solution than this big case statement ? }
  184. { ok, a proc table would do the job }
  185. case tstringdef(resulttype.def).string_typ of
  186. st_shortstring:
  187. case tstringdef(left.resulttype.def).string_typ of
  188. st_shortstring:
  189. begin
  190. gettempofsizereference(resulttype.def.size,location.reference);
  191. copyshortstring(location.reference,left.location.reference,
  192. tstringdef(resulttype.def).len,false,true);
  193. { done by copyshortstring now (JM) }
  194. { del_reference(left.location.reference); }
  195. ungetiftemp(left.location.reference);
  196. end;
  197. st_longstring:
  198. begin
  199. {!!!!!!!}
  200. internalerror(8888);
  201. end;
  202. st_ansistring:
  203. begin
  204. gettempofsizereference(resulttype.def.size,location.reference);
  205. loadansi2short(left,self);
  206. { this is done in secondtypeconv (FK)
  207. removetemps(exprasmlist,temptoremove);
  208. destroys:=true;
  209. }
  210. end;
  211. st_widestring:
  212. begin
  213. {!!!!!!!}
  214. internalerror(8888);
  215. end;
  216. end;
  217. st_longstring:
  218. case tstringdef(left.resulttype.def).string_typ of
  219. st_shortstring:
  220. begin
  221. {!!!!!!!}
  222. internalerror(8888);
  223. end;
  224. st_ansistring:
  225. begin
  226. {!!!!!!!}
  227. internalerror(8888);
  228. end;
  229. st_widestring:
  230. begin
  231. {!!!!!!!}
  232. internalerror(8888);
  233. end;
  234. end;
  235. st_ansistring:
  236. case tstringdef(left.resulttype.def).string_typ of
  237. st_shortstring:
  238. begin
  239. clear_location(location);
  240. location.loc:=LOC_REFERENCE;
  241. gettempansistringreference(location.reference);
  242. decrstringref(cansistringtype.def,location.reference);
  243. { We don't need the source regs anymore (JM) }
  244. regs_to_push := $ff;
  245. remove_non_regvars_from_loc(left.location,regs_to_push);
  246. pushusedregisters(pushed,regs_to_push);
  247. release_loc(left.location);
  248. emit_push_lea_loc(left.location,true);
  249. emit_push_lea_loc(location,false);
  250. saveregvars(regs_to_push);
  251. emitcall('FPC_SHORTSTR_TO_ANSISTR');
  252. maybe_loadself;
  253. popusedregisters(pushed);
  254. end;
  255. st_longstring:
  256. begin
  257. {!!!!!!!}
  258. internalerror(8888);
  259. end;
  260. st_widestring:
  261. begin
  262. {!!!!!!!}
  263. internalerror(8888);
  264. end;
  265. end;
  266. st_widestring:
  267. case tstringdef(left.resulttype.def).string_typ of
  268. st_shortstring:
  269. begin
  270. {!!!!!!!}
  271. internalerror(8888);
  272. end;
  273. st_longstring:
  274. begin
  275. {!!!!!!!}
  276. internalerror(8888);
  277. end;
  278. st_ansistring:
  279. begin
  280. {!!!!!!!}
  281. internalerror(8888);
  282. end;
  283. st_widestring:
  284. begin
  285. {!!!!!!!}
  286. internalerror(8888);
  287. end;
  288. end;
  289. end;
  290. end;
  291. procedure ti386typeconvnode.second_cstring_to_pchar;
  292. var
  293. hr : preference;
  294. begin
  295. clear_location(location);
  296. location.loc:=LOC_REGISTER;
  297. location.register:=getregister32;
  298. case tstringdef(left.resulttype.def).string_typ of
  299. st_shortstring :
  300. begin
  301. inc(left.location.reference.offset);
  302. emit_ref_reg(A_LEA,S_L,newreference(left.location.reference),
  303. location.register);
  304. end;
  305. st_ansistring :
  306. begin
  307. if (left.nodetype=stringconstn) and
  308. (str_length(left)=0) then
  309. begin
  310. new(hr);
  311. reset_reference(hr^);
  312. hr^.symbol:=newasmsymbol('FPC_EMPTYCHAR');
  313. emit_ref_reg(A_LEA,S_L,hr,location.register);
  314. end
  315. else
  316. emit_ref_reg(A_MOV,S_L,newreference(left.location.reference),
  317. location.register);
  318. end;
  319. st_longstring:
  320. begin
  321. {!!!!!!!}
  322. internalerror(8888);
  323. end;
  324. st_widestring:
  325. begin
  326. {!!!!!!!}
  327. internalerror(8888);
  328. end;
  329. end;
  330. end;
  331. procedure ti386typeconvnode.second_string_to_chararray;
  332. var
  333. pushedregs: tpushed;
  334. //l1 : tasmlabel;
  335. //hr : preference;
  336. arrsize, strtype: longint;
  337. regstopush: byte;
  338. begin
  339. with tarraydef(resulttype.def) do
  340. begin
  341. if highrange<lowrange then
  342. internalerror(75432653);
  343. arrsize := highrange-lowrange+1;
  344. end;
  345. if (left.nodetype = stringconstn) and
  346. { left.length+1 since there's always a terminating #0 character (JM) }
  347. (tstringconstnode(left).len+1 >= arrsize) and
  348. (tstringdef(left.resulttype.def).string_typ=st_shortstring) then
  349. begin
  350. inc(location.reference.offset);
  351. exit;
  352. end;
  353. clear_location(location);
  354. location.loc := LOC_REFERENCE;
  355. gettempofsizereference(arrsize,location.reference);
  356. regstopush := $ff;
  357. remove_non_regvars_from_loc(left.location,regstopush);
  358. pushusedregisters(pushedregs,regstopush);
  359. emit_push_lea_loc(location,false);
  360. case tstringdef(left.resulttype.def).string_typ of
  361. st_shortstring :
  362. begin
  363. { 0 means shortstring }
  364. strtype := 0;
  365. del_reference(left.location.reference);
  366. emit_push_lea_loc(left.location,true);
  367. ungetiftemp(left.location.reference);
  368. end;
  369. st_ansistring :
  370. begin
  371. { 1 means ansistring }
  372. strtype := 1;
  373. case left.location.loc of
  374. LOC_CREGISTER,LOC_REGISTER:
  375. begin
  376. ungetregister(left.location.register);
  377. emit_push_loc(left.location);
  378. end;
  379. LOC_MEM,LOC_REFERENCE:
  380. begin
  381. del_reference(left.location.reference);
  382. emit_push_loc(left.location);
  383. ungetiftemp(left.location.reference);
  384. end;
  385. end;
  386. end;
  387. st_longstring:
  388. begin
  389. {!!!!!!!}
  390. { 2 means longstring, but still needs support in FPC_STR_TO_CHARARRAY,
  391. which is in i386.inc and/or generic.inc (JM) }
  392. strtype := 2;
  393. internalerror(8888);
  394. end;
  395. st_widestring:
  396. begin
  397. {!!!!!!!}
  398. { 3 means widestring, but still needs support in FPC_STR_TO_CHARARRAY,
  399. which is in i386.inc and/or generic.inc (JM) }
  400. strtype := 3;
  401. internalerror(8888);
  402. end;
  403. end;
  404. push_int(arrsize);
  405. push_int(strtype);
  406. saveregvars(regstopush);
  407. emitcall('FPC_STR_TO_CHARARRAY');
  408. popusedregisters(pushedregs);
  409. end;
  410. procedure ti386typeconvnode.second_array_to_pointer;
  411. begin
  412. del_reference(left.location.reference);
  413. clear_location(location);
  414. location.loc:=LOC_REGISTER;
  415. location.register:=getregister32;
  416. emit_ref_reg(A_LEA,S_L,newreference(left.location.reference),
  417. location.register);
  418. end;
  419. procedure ti386typeconvnode.second_pointer_to_array;
  420. begin
  421. clear_location(location);
  422. location.loc:=LOC_REFERENCE;
  423. reset_reference(location.reference);
  424. case left.location.loc of
  425. LOC_REGISTER :
  426. location.reference.base:=left.location.register;
  427. LOC_CREGISTER :
  428. begin
  429. location.reference.base:=getregister32;
  430. emit_reg_reg(A_MOV,S_L,left.location.register,location.reference.base);
  431. end
  432. else
  433. begin
  434. del_reference(left.location.reference);
  435. location.reference.base:=getregister32;
  436. emit_ref_reg(A_MOV,S_L,newreference(left.location.reference),
  437. location.reference.base);
  438. end;
  439. end;
  440. end;
  441. { generates the code for the type conversion from an array of char }
  442. { to a string }
  443. procedure ti386typeconvnode.second_chararray_to_string;
  444. var
  445. pushed : tpushed;
  446. regstopush: byte;
  447. l : longint;
  448. begin
  449. { calc the length of the array }
  450. l:=tarraydef(left.resulttype.def).highrange-tarraydef(left.resulttype.def).lowrange+1;
  451. { this is a type conversion which copies the data, so we can't }
  452. { return a reference }
  453. clear_location(location);
  454. location.loc:=LOC_MEM;
  455. case tstringdef(resulttype.def).string_typ of
  456. st_shortstring :
  457. begin
  458. if l>255 then
  459. begin
  460. CGMessage(type_e_mismatch);
  461. l:=255;
  462. end;
  463. gettempofsizereference(resulttype.def.size,location.reference);
  464. { we've also to release the registers ... }
  465. { Yes, but before pushusedregisters since that one resets unused! }
  466. { This caused web bug 1073 (JM) }
  467. regstopush := $ff;
  468. remove_non_regvars_from_loc(left.location,regstopush);
  469. pushusedregisters(pushed,regstopush);
  470. if l>=resulttype.def.size then
  471. push_int(resulttype.def.size-1)
  472. else
  473. push_int(l);
  474. { ... here only the temp. location is released }
  475. emit_push_lea_loc(left.location,true);
  476. del_reference(left.location.reference);
  477. emitpushreferenceaddr(location.reference);
  478. saveregvars(regstopush);
  479. emitcall('FPC_CHARARRAY_TO_SHORTSTR');
  480. maybe_loadself;
  481. popusedregisters(pushed);
  482. end;
  483. st_ansistring :
  484. begin
  485. gettempansistringreference(location.reference);
  486. decrstringref(cansistringtype.def,location.reference);
  487. regstopush := $ff;
  488. remove_non_regvars_from_loc(left.location,regstopush);
  489. pushusedregisters(pushed,regstopush);
  490. push_int(l);
  491. emitpushreferenceaddr(left.location.reference);
  492. release_loc(left.location);
  493. emitpushreferenceaddr(location.reference);
  494. saveregvars(regstopush);
  495. emitcall('FPC_CHARARRAY_TO_ANSISTR');
  496. popusedregisters(pushed);
  497. maybe_loadself;
  498. end;
  499. st_longstring:
  500. begin
  501. {!!!!!!!}
  502. internalerror(8888);
  503. end;
  504. st_widestring:
  505. begin
  506. {!!!!!!!}
  507. internalerror(8888);
  508. end;
  509. end;
  510. end;
  511. procedure ti386typeconvnode.second_char_to_string;
  512. var
  513. pushed : tpushed;
  514. begin
  515. clear_location(location);
  516. location.loc:=LOC_MEM;
  517. case tstringdef(resulttype.def).string_typ of
  518. st_shortstring :
  519. begin
  520. gettempofsizereference(256,location.reference);
  521. loadshortstring(left,self);
  522. end;
  523. st_ansistring :
  524. begin
  525. gettempansistringreference(location.reference);
  526. decrstringref(cansistringtype.def,location.reference);
  527. release_loc(left.location);
  528. pushusedregisters(pushed,$ff);
  529. emit_pushw_loc(left.location);
  530. emitpushreferenceaddr(location.reference);
  531. saveregvars($ff);
  532. emitcall('FPC_CHAR_TO_ANSISTR');
  533. popusedregisters(pushed);
  534. maybe_loadself;
  535. end;
  536. else
  537. internalerror(4179);
  538. end;
  539. end;
  540. procedure ti386typeconvnode.second_int_to_real;
  541. var
  542. r : preference;
  543. hregister : tregister;
  544. l1,l2 : tasmlabel;
  545. begin
  546. { for u32bit a solution is to push $0 and to load a comp }
  547. { does this first, it destroys maybe EDI }
  548. hregister:=R_EDI;
  549. if torddef(left.resulttype.def).typ=u32bit then
  550. push_int(0);
  551. if (left.location.loc=LOC_REGISTER) or
  552. (left.location.loc=LOC_CREGISTER) then
  553. begin
  554. if not (torddef(left.resulttype.def).typ in [u32bit,s32bit,u64bit,s64bit]) then
  555. getexplicitregister32(R_EDI);
  556. case torddef(left.resulttype.def).typ of
  557. s8bit : emit_reg_reg(A_MOVSX,S_BL,left.location.register,R_EDI);
  558. u8bit : emit_reg_reg(A_MOVZX,S_BL,left.location.register,R_EDI);
  559. s16bit : emit_reg_reg(A_MOVSX,S_WL,left.location.register,R_EDI);
  560. u16bit : emit_reg_reg(A_MOVZX,S_WL,left.location.register,R_EDI);
  561. u32bit,s32bit:
  562. hregister:=left.location.register;
  563. u64bit,s64bit:
  564. begin
  565. emit_reg(A_PUSH,S_L,left.location.registerhigh);
  566. hregister:=left.location.registerlow;
  567. end;
  568. end;
  569. ungetregister(left.location.register);
  570. end
  571. else
  572. begin
  573. r:=newreference(left.location.reference);
  574. getexplicitregister32(R_EDI);
  575. case torddef(left.resulttype.def).typ of
  576. s8bit:
  577. emit_ref_reg(A_MOVSX,S_BL,r,R_EDI);
  578. u8bit:
  579. emit_ref_reg(A_MOVZX,S_BL,r,R_EDI);
  580. s16bit:
  581. emit_ref_reg(A_MOVSX,S_WL,r,R_EDI);
  582. u16bit:
  583. emit_ref_reg(A_MOVZX,S_WL,r,R_EDI);
  584. u32bit,s32bit:
  585. emit_ref_reg(A_MOV,S_L,r,R_EDI);
  586. u64bit,s64bit:
  587. begin
  588. inc(r^.offset,4);
  589. emit_ref_reg(A_MOV,S_L,r,R_EDI);
  590. emit_reg(A_PUSH,S_L,R_EDI);
  591. r:=newreference(left.location.reference);
  592. emit_ref_reg(A_MOV,S_L,r,R_EDI);
  593. end;
  594. end;
  595. del_reference(left.location.reference);
  596. ungetiftemp(left.location.reference);
  597. end;
  598. { for 64 bit integers, the high dword is already pushed }
  599. emit_reg(A_PUSH,S_L,hregister);
  600. if hregister = R_EDI then
  601. ungetregister32(R_EDI);
  602. r:=new_reference(R_ESP,0);
  603. case torddef(left.resulttype.def).typ of
  604. u32bit:
  605. begin
  606. emit_ref(A_FILD,S_IQ,r);
  607. emit_const_reg(A_ADD,S_L,8,R_ESP);
  608. end;
  609. s64bit:
  610. begin
  611. emit_ref(A_FILD,S_IQ,r);
  612. emit_const_reg(A_ADD,S_L,8,R_ESP);
  613. end;
  614. u64bit:
  615. begin
  616. { unsigned 64 bit ints are harder to handle: }
  617. { we load bits 0..62 and then check bit 63: }
  618. { if it is 1 then we add $80000000 000000000 }
  619. { as double }
  620. inc(r^.offset,4);
  621. getexplicitregister32(R_EDI);
  622. emit_ref_reg(A_MOV,S_L,r,R_EDI);
  623. r:=new_reference(R_ESP,4);
  624. emit_const_ref(A_AND,S_L,$7fffffff,r);
  625. emit_const_reg(A_TEST,S_L,longint($80000000),R_EDI);
  626. ungetregister32(R_EDI);
  627. r:=new_reference(R_ESP,0);
  628. emit_ref(A_FILD,S_IQ,r);
  629. getdatalabel(l1);
  630. getlabel(l2);
  631. emitjmp(C_Z,l2);
  632. Consts.concat(Tai_label.Create(l1));
  633. { I got this constant from a test progtram (FK) }
  634. Consts.concat(Tai_const.Create_32bit(0));
  635. Consts.concat(Tai_const.Create_32bit(1138753536));
  636. r:=new_reference(R_NO,0);
  637. r^.symbol:=l1;
  638. emit_ref(A_FADD,S_FL,r);
  639. emitlab(l2);
  640. emit_const_reg(A_ADD,S_L,8,R_ESP);
  641. end
  642. else
  643. begin
  644. emit_ref(A_FILD,S_IL,r);
  645. getexplicitregister32(R_EDI);
  646. emit_reg(A_POP,S_L,R_EDI);
  647. ungetregister32(R_EDI);
  648. end;
  649. end;
  650. inc(fpuvaroffset);
  651. clear_location(location);
  652. location.loc:=LOC_FPU;
  653. end;
  654. procedure ti386typeconvnode.second_real_to_real;
  655. begin
  656. case left.location.loc of
  657. LOC_FPU : ;
  658. LOC_CFPUREGISTER:
  659. begin
  660. location:=left.location;
  661. exit;
  662. end;
  663. LOC_MEM,
  664. LOC_REFERENCE:
  665. begin
  666. floatload(tfloatdef(left.resulttype.def).typ,
  667. left.location.reference);
  668. { we have to free the reference }
  669. del_reference(left.location.reference);
  670. end;
  671. end;
  672. clear_location(location);
  673. location.loc:=LOC_FPU;
  674. end;
  675. procedure ti386typeconvnode.second_cord_to_pointer;
  676. begin
  677. { this can't happend, because constants are already processed in
  678. pass 1 }
  679. internalerror(47423985);
  680. end;
  681. procedure ti386typeconvnode.second_proc_to_procvar;
  682. begin
  683. { method pointer ? }
  684. if assigned(tcallnode(left).left) then
  685. begin
  686. set_location(location,left.location);
  687. end
  688. else
  689. begin
  690. clear_location(location);
  691. location.loc:=LOC_REGISTER;
  692. location.register:=getregister32;
  693. del_reference(left.location.reference);
  694. emit_ref_reg(A_LEA,S_L,
  695. newreference(left.location.reference),location.register);
  696. end;
  697. end;
  698. procedure ti386typeconvnode.second_bool_to_int;
  699. var
  700. oldtruelabel,oldfalselabel,hlabel : tasmlabel;
  701. hregister : tregister;
  702. newsize,
  703. opsize : topsize;
  704. op : tasmop;
  705. begin
  706. oldtruelabel:=truelabel;
  707. oldfalselabel:=falselabel;
  708. getlabel(truelabel);
  709. getlabel(falselabel);
  710. secondpass(left);
  711. { byte(boolean) or word(wordbool) or longint(longbool) must
  712. be accepted for var parameters }
  713. if (nf_explizit in flags) and
  714. (left.resulttype.def.size=resulttype.def.size) and
  715. (left.location.loc in [LOC_REFERENCE,LOC_MEM,LOC_CREGISTER]) then
  716. begin
  717. set_location(location,left.location);
  718. truelabel:=oldtruelabel;
  719. falselabel:=oldfalselabel;
  720. exit;
  721. end;
  722. clear_location(location);
  723. location.loc:=LOC_REGISTER;
  724. del_reference(left.location.reference);
  725. case left.resulttype.def.size of
  726. 1 : begin
  727. case resulttype.def.size of
  728. 1 : opsize:=S_B;
  729. 2 : opsize:=S_BW;
  730. 4 : opsize:=S_BL;
  731. end;
  732. end;
  733. 2 : begin
  734. case resulttype.def.size of
  735. 1 : begin
  736. if left.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
  737. left.location.register:=reg16toreg8(left.location.register);
  738. opsize:=S_B;
  739. end;
  740. 2 : opsize:=S_W;
  741. 4 : opsize:=S_WL;
  742. end;
  743. end;
  744. 4 : begin
  745. case resulttype.def.size of
  746. 1 : begin
  747. if left.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
  748. left.location.register:=reg32toreg8(left.location.register);
  749. opsize:=S_B;
  750. end;
  751. 2 : begin
  752. if left.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
  753. left.location.register:=reg32toreg16(left.location.register);
  754. opsize:=S_W;
  755. end;
  756. 4 : opsize:=S_L;
  757. end;
  758. end;
  759. end;
  760. if opsize in [S_B,S_W,S_L] then
  761. op:=A_MOV
  762. else
  763. if is_signed(resulttype.def) then
  764. op:=A_MOVSX
  765. else
  766. op:=A_MOVZX;
  767. hregister:=getregister32;
  768. case resulttype.def.size of
  769. 1 : begin
  770. location.register:=reg32toreg8(hregister);
  771. newsize:=S_B;
  772. end;
  773. 2 : begin
  774. location.register:=reg32toreg16(hregister);
  775. newsize:=S_W;
  776. end;
  777. 4 : begin
  778. location.register:=hregister;
  779. newsize:=S_L;
  780. end;
  781. else
  782. internalerror(10060);
  783. end;
  784. case left.location.loc of
  785. LOC_MEM,
  786. LOC_REFERENCE : emit_ref_reg(op,opsize,
  787. newreference(left.location.reference),location.register);
  788. LOC_REGISTER,
  789. LOC_CREGISTER : begin
  790. { remove things like movb %al,%al }
  791. if left.location.register<>location.register then
  792. emit_reg_reg(op,opsize,
  793. left.location.register,location.register);
  794. end;
  795. LOC_FLAGS : begin
  796. emit_flag2reg(left.location.resflags,location.register);
  797. end;
  798. LOC_JUMP : begin
  799. getlabel(hlabel);
  800. emitlab(truelabel);
  801. emit_const_reg(A_MOV,newsize,1,location.register);
  802. emitjmp(C_None,hlabel);
  803. emitlab(falselabel);
  804. emit_reg_reg(A_XOR,newsize,location.register,
  805. location.register);
  806. emitlab(hlabel);
  807. end;
  808. else
  809. internalerror(10061);
  810. end;
  811. truelabel:=oldtruelabel;
  812. falselabel:=oldfalselabel;
  813. end;
  814. procedure ti386typeconvnode.second_int_to_bool;
  815. var
  816. hregister : tregister;
  817. resflags : tresflags;
  818. opsize : topsize;
  819. begin
  820. clear_location(location);
  821. { byte(boolean) or word(wordbool) or longint(longbool) must
  822. be accepted for var parameters }
  823. if (nf_explizit in flags) and
  824. (left.resulttype.def.size=resulttype.def.size) and
  825. (left.location.loc in [LOC_REFERENCE,LOC_MEM,LOC_CREGISTER]) then
  826. begin
  827. set_location(location,left.location);
  828. exit;
  829. end;
  830. location.loc:=LOC_REGISTER;
  831. del_reference(left.location.reference);
  832. opsize:=def_opsize(left.resulttype.def);
  833. case left.location.loc of
  834. LOC_MEM,LOC_REFERENCE :
  835. begin
  836. hregister:=def_getreg(left.resulttype.def);
  837. emit_ref_reg(A_MOV,opsize,
  838. newreference(left.location.reference),hregister);
  839. emit_reg_reg(A_OR,opsize,hregister,hregister);
  840. resflags:=F_NE;
  841. end;
  842. LOC_FLAGS :
  843. begin
  844. hregister:=getregister32;
  845. resflags:=left.location.resflags;
  846. end;
  847. LOC_REGISTER,LOC_CREGISTER :
  848. begin
  849. hregister:=left.location.register;
  850. emit_reg_reg(A_OR,opsize,hregister,hregister);
  851. resflags:=F_NE;
  852. end;
  853. else
  854. internalerror(10062);
  855. end;
  856. case resulttype.def.size of
  857. 1 : location.register:=makereg8(hregister);
  858. 2 : location.register:=makereg16(hregister);
  859. 4 : location.register:=makereg32(hregister);
  860. else
  861. internalerror(10064);
  862. end;
  863. emit_flag2reg(resflags,location.register);
  864. end;
  865. procedure ti386typeconvnode.second_load_smallset;
  866. var
  867. href : treference;
  868. pushedregs : tpushed;
  869. begin
  870. href.symbol:=nil;
  871. pushusedregisters(pushedregs,$ff);
  872. gettempofsizereference(32,href);
  873. emit_push_mem_size(left.location.reference,4);
  874. emitpushreferenceaddr(href);
  875. saveregvars($ff);
  876. emitcall('FPC_SET_LOAD_SMALL');
  877. maybe_loadself;
  878. popusedregisters(pushedregs);
  879. clear_location(location);
  880. location.loc:=LOC_MEM;
  881. location.reference:=href;
  882. end;
  883. procedure ti386typeconvnode.second_ansistring_to_pchar;
  884. var
  885. l1 : tasmlabel;
  886. hr : preference;
  887. begin
  888. clear_location(location);
  889. location.loc:=LOC_REGISTER;
  890. getlabel(l1);
  891. case left.location.loc of
  892. LOC_CREGISTER,LOC_REGISTER:
  893. location.register:=left.location.register;
  894. LOC_MEM,LOC_REFERENCE:
  895. begin
  896. location.register:=getregister32;
  897. emit_ref_reg(A_MOV,S_L,newreference(left.location.reference),
  898. location.register);
  899. del_reference(left.location.reference);
  900. end;
  901. end;
  902. emit_const_reg(A_CMP,S_L,0,location.register);
  903. emitjmp(C_NZ,l1);
  904. new(hr);
  905. reset_reference(hr^);
  906. hr^.symbol:=newasmsymbol('FPC_EMPTYCHAR');
  907. emit_ref_reg(A_LEA,S_L,hr,location.register);
  908. emitlab(l1);
  909. end;
  910. procedure ti386typeconvnode.second_pchar_to_string;
  911. var
  912. pushed : tpushed;
  913. regs_to_push: byte;
  914. begin
  915. case tstringdef(resulttype.def).string_typ of
  916. st_shortstring:
  917. begin
  918. location.loc:=LOC_REFERENCE;
  919. gettempofsizereference(resulttype.def.size,location.reference);
  920. pushusedregisters(pushed,$ff);
  921. case left.location.loc of
  922. LOC_REGISTER,LOC_CREGISTER:
  923. begin
  924. emit_reg(A_PUSH,S_L,left.location.register);
  925. ungetregister32(left.location.register);
  926. end;
  927. LOC_REFERENCE,LOC_MEM:
  928. begin
  929. { Now release the registers (see cgai386.pas: }
  930. { loadansistring for more info on the order) (JM) }
  931. del_reference(left.location.reference);
  932. emit_push_mem(left.location.reference);
  933. end;
  934. end;
  935. emitpushreferenceaddr(location.reference);
  936. saveregvars($ff);
  937. emitcall('FPC_PCHAR_TO_SHORTSTR');
  938. maybe_loadself;
  939. popusedregisters(pushed);
  940. end;
  941. st_ansistring:
  942. begin
  943. location.loc:=LOC_REFERENCE;
  944. gettempansistringreference(location.reference);
  945. decrstringref(cansistringtype.def,location.reference);
  946. { Find out which regs have to be pushed (JM) }
  947. regs_to_push := $ff;
  948. remove_non_regvars_from_loc(left.location,regs_to_push);
  949. pushusedregisters(pushed,regs_to_push);
  950. case left.location.loc of
  951. LOC_REFERENCE,LOC_MEM:
  952. begin
  953. { Now release the registers (see cgai386.pas: }
  954. { loadansistring for more info on the order) (JM) }
  955. del_reference(left.location.reference);
  956. emit_push_mem(left.location.reference);
  957. end;
  958. LOC_REGISTER,LOC_CREGISTER:
  959. begin
  960. { Now release the registers (see cgai386.pas: }
  961. { loadansistring for more info on the order) (JM) }
  962. emit_reg(A_PUSH,S_L,left.location.register);
  963. ungetregister32(left.location.register);
  964. end;
  965. end;
  966. emitpushreferenceaddr(location.reference);
  967. saveregvars(regs_to_push);
  968. emitcall('FPC_PCHAR_TO_ANSISTR');
  969. maybe_loadself;
  970. popusedregisters(pushed);
  971. end;
  972. else
  973. begin
  974. internalerror(12121);
  975. end;
  976. end;
  977. end;
  978. procedure ti386typeconvnode.second_class_to_intf;
  979. var
  980. hreg : tregister;
  981. l1 : tasmlabel;
  982. begin
  983. case left.location.loc of
  984. LOC_MEM,
  985. LOC_REFERENCE:
  986. begin
  987. del_reference(left.location.reference);
  988. hreg:=getregister32;
  989. exprasmList.concat(Taicpu.Op_ref_reg(
  990. A_MOV,S_L,newreference(left.location.reference),hreg));
  991. end;
  992. LOC_CREGISTER:
  993. begin
  994. hreg:=getregister32;
  995. exprasmList.concat(Taicpu.Op_reg_reg(
  996. A_MOV,S_L,left.location.register,hreg));
  997. end;
  998. LOC_REGISTER:
  999. hreg:=left.location.register;
  1000. else internalerror(121120001);
  1001. end;
  1002. emit_reg_reg(A_TEST,S_L,hreg,hreg);
  1003. getlabel(l1);
  1004. emitjmp(C_Z,l1);
  1005. emit_const_reg(A_ADD,S_L,tobjectdef(left.resulttype.def).implementedinterfaces.ioffsets(
  1006. tobjectdef(left.resulttype.def).implementedinterfaces.searchintf(resulttype.def))^,hreg);
  1007. emitlab(l1);
  1008. location.loc:=LOC_REGISTER;
  1009. location.register:=hreg;
  1010. end;
  1011. procedure ti386typeconvnode.second_nothing;
  1012. begin
  1013. end;
  1014. {****************************************************************************
  1015. TI386TYPECONVNODE
  1016. ****************************************************************************}
  1017. procedure ti386typeconvnode.second_call_helper(c : tconverttype);
  1018. const
  1019. secondconvert : array[tconverttype] of pointer = (
  1020. @ti386typeconvnode.second_nothing, {equal}
  1021. @ti386typeconvnode.second_nothing, {not_possible}
  1022. @ti386typeconvnode.second_string_to_string,
  1023. @ti386typeconvnode.second_char_to_string,
  1024. @ti386typeconvnode.second_pchar_to_string,
  1025. @ti386typeconvnode.second_nothing, {cchar_to_pchar}
  1026. @ti386typeconvnode.second_cstring_to_pchar,
  1027. @ti386typeconvnode.second_ansistring_to_pchar,
  1028. @ti386typeconvnode.second_string_to_chararray,
  1029. @ti386typeconvnode.second_chararray_to_string,
  1030. @ti386typeconvnode.second_array_to_pointer,
  1031. @ti386typeconvnode.second_pointer_to_array,
  1032. @ti386typeconvnode.second_int_to_int,
  1033. @ti386typeconvnode.second_int_to_bool,
  1034. @ti386typeconvnode.second_bool_to_int, { bool_to_bool }
  1035. @ti386typeconvnode.second_bool_to_int,
  1036. @ti386typeconvnode.second_real_to_real,
  1037. @ti386typeconvnode.second_int_to_real,
  1038. @ti386typeconvnode.second_proc_to_procvar,
  1039. @ti386typeconvnode.second_nothing, {arrayconstructor_to_set}
  1040. @ti386typeconvnode.second_load_smallset,
  1041. @ti386typeconvnode.second_cord_to_pointer,
  1042. @ti386typeconvnode.second_nothing, { interface 2 string }
  1043. @ti386typeconvnode.second_nothing, { interface 2 guid }
  1044. @ti386typeconvnode.second_class_to_intf
  1045. );
  1046. type
  1047. tprocedureofobject = procedure of object;
  1048. var
  1049. r : packed record
  1050. proc : pointer;
  1051. obj : pointer;
  1052. end;
  1053. begin
  1054. { this is a little bit dirty but it works }
  1055. { and should be quite portable too }
  1056. r.proc:=secondconvert[c];
  1057. r.obj:=self;
  1058. tprocedureofobject(r){$ifdef FPC}();{$endif FPC}
  1059. end;
  1060. procedure ti386typeconvnode.pass_2;
  1061. {$ifdef TESTOBJEXT2}
  1062. var
  1063. r : preference;
  1064. nillabel : plabel;
  1065. {$endif TESTOBJEXT2}
  1066. begin
  1067. { this isn't good coding, I think tc_bool_2_int, shouldn't be }
  1068. { type conversion (FK) }
  1069. if not(convtype in [tc_bool_2_int,tc_bool_2_bool]) then
  1070. begin
  1071. secondpass(left);
  1072. set_location(location,left.location);
  1073. if codegenerror then
  1074. exit;
  1075. end;
  1076. second_call_helper(convtype);
  1077. {$ifdef TESTOBJEXT2}
  1078. { Check explicit conversions to objects pointers !! }
  1079. if p^.explizit and
  1080. (p^.resulttype.def.deftype=pointerdef) and
  1081. (tpointerdef(p^.resulttype.def).definition.deftype=objectdef) and not
  1082. (tobjectdef(tpointerdef(p^.resulttype.def).definition).isclass) and
  1083. ((tobjectdef(tpointerdef(p^.resulttype.def).definition).options and oo_hasvmt)<>0) and
  1084. (cs_check_range in aktlocalswitches) then
  1085. begin
  1086. new(r);
  1087. reset_reference(r^);
  1088. if p^.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
  1089. r^.base:=p^.location.register
  1090. else
  1091. begin
  1092. getexplicitregister32(R_EDI);
  1093. emit_mov_loc_reg(p^.location,R_EDI);
  1094. r^.base:=R_EDI;
  1095. end;
  1096. { NIL must be accepted !! }
  1097. emit_reg_reg(A_OR,S_L,r^.base,r^.base);
  1098. ungetregister32(R_EDI);
  1099. getlabel(nillabel);
  1100. emitjmp(C_E,nillabel);
  1101. { this is one point where we need vmt_offset (PM) }
  1102. r^.offset:= tobjectdef(tpointerdef(p^.resulttype.def).definition).vmt_offset;
  1103. getexplicitregister32(R_EDI);
  1104. emit_ref_reg(A_MOV,S_L,r,R_EDI);
  1105. emit_sym(A_PUSH,S_L,
  1106. newasmsymbol(tobjectdef(tpointerdef(p^.resulttype.def).definition).vmt_mangledname));
  1107. emit_reg(A_PUSH,S_L,R_EDI);
  1108. ungetregister32(R_EDI);
  1109. emitcall('FPC_CHECK_OBJECT_EXT');
  1110. emitlab(nillabel);
  1111. end;
  1112. {$endif TESTOBJEXT2}
  1113. end;
  1114. {*****************************************************************************
  1115. TI386ISNODE
  1116. *****************************************************************************}
  1117. procedure ti386isnode.pass_2;
  1118. var
  1119. pushed : tpushed;
  1120. begin
  1121. { save all used registers }
  1122. pushusedregisters(pushed,$ff);
  1123. secondpass(left);
  1124. clear_location(location);
  1125. location.loc:=LOC_FLAGS;
  1126. location.resflags:=F_NE;
  1127. { push instance to check: }
  1128. case left.location.loc of
  1129. LOC_REGISTER,LOC_CREGISTER:
  1130. begin
  1131. emit_reg(A_PUSH,
  1132. S_L,left.location.register);
  1133. ungetregister32(left.location.register);
  1134. end;
  1135. LOC_MEM,LOC_REFERENCE:
  1136. begin
  1137. emit_ref(A_PUSH,
  1138. S_L,newreference(left.location.reference));
  1139. del_reference(left.location.reference);
  1140. end;
  1141. else internalerror(100);
  1142. end;
  1143. { generate type checking }
  1144. secondpass(right);
  1145. case right.location.loc of
  1146. LOC_REGISTER,LOC_CREGISTER:
  1147. begin
  1148. emit_reg(A_PUSH,
  1149. S_L,right.location.register);
  1150. ungetregister32(right.location.register);
  1151. end;
  1152. LOC_MEM,LOC_REFERENCE:
  1153. begin
  1154. emit_ref(A_PUSH,
  1155. S_L,newreference(right.location.reference));
  1156. del_reference(right.location.reference);
  1157. end;
  1158. else internalerror(100);
  1159. end;
  1160. saveregvars($ff);
  1161. emitcall('FPC_DO_IS');
  1162. emit_reg_reg(A_OR,S_B,R_AL,R_AL);
  1163. popusedregisters(pushed);
  1164. maybe_loadself;
  1165. end;
  1166. {*****************************************************************************
  1167. TI386ASNODE
  1168. *****************************************************************************}
  1169. procedure ti386asnode.pass_2;
  1170. var
  1171. pushed : tpushed;
  1172. begin
  1173. secondpass(left);
  1174. { save all used registers }
  1175. pushusedregisters(pushed,$ff);
  1176. { push instance to check: }
  1177. case left.location.loc of
  1178. LOC_REGISTER,LOC_CREGISTER:
  1179. emit_reg(A_PUSH,
  1180. S_L,left.location.register);
  1181. LOC_MEM,LOC_REFERENCE:
  1182. emit_ref(A_PUSH,
  1183. S_L,newreference(left.location.reference));
  1184. else internalerror(100);
  1185. end;
  1186. { we doesn't modifiy the left side, we check only the type }
  1187. set_location(location,left.location);
  1188. { generate type checking }
  1189. secondpass(right);
  1190. case right.location.loc of
  1191. LOC_REGISTER,LOC_CREGISTER:
  1192. begin
  1193. emit_reg(A_PUSH,
  1194. S_L,right.location.register);
  1195. ungetregister32(right.location.register);
  1196. end;
  1197. LOC_MEM,LOC_REFERENCE:
  1198. begin
  1199. emit_ref(A_PUSH,
  1200. S_L,newreference(right.location.reference));
  1201. del_reference(right.location.reference);
  1202. end;
  1203. else internalerror(100);
  1204. end;
  1205. saveregvars($ff);
  1206. emitcall('FPC_DO_AS');
  1207. { restore register, this restores automatically the }
  1208. { result }
  1209. popusedregisters(pushed);
  1210. maybe_loadself;
  1211. end;
  1212. begin
  1213. ctypeconvnode:=ti386typeconvnode;
  1214. cisnode:=ti386isnode;
  1215. casnode:=ti386asnode;
  1216. end.
  1217. {
  1218. $Log$
  1219. Revision 1.14 2001-04-13 01:22:18 peter
  1220. * symtable change to classes
  1221. * range check generation and errors fixed, make cycle DEBUG=1 works
  1222. * memory leaks fixed
  1223. Revision 1.13 2001/04/02 21:20:36 peter
  1224. * resulttype rewrite
  1225. Revision 1.12 2001/01/08 21:45:11 peter
  1226. * internalerror for string to chararray
  1227. Revision 1.11 2000/12/25 00:07:32 peter
  1228. + new tlinkedlist class (merge of old tstringqueue,tcontainer and
  1229. tlinkedlist objects)
  1230. Revision 1.10 2000/12/07 17:19:46 jonas
  1231. * new constant handling: from now on, hex constants >$7fffffff are
  1232. parsed as unsigned constants (otherwise, $80000000 got sign extended
  1233. and became $ffffffff80000000), all constants in the longint range
  1234. become longints, all constants >$7fffffff and <=cardinal($ffffffff)
  1235. are cardinals and the rest are int64's.
  1236. * added lots of longint typecast to prevent range check errors in the
  1237. compiler and rtl
  1238. * type casts of symbolic ordinal constants are now preserved
  1239. * fixed bug where the original resulttype.def wasn't restored correctly
  1240. after doing a 64bit rangecheck
  1241. Revision 1.9 2000/12/05 11:44:33 jonas
  1242. + new integer regvar handling, should be much more efficient
  1243. Revision 1.8 2000/11/29 00:30:46 florian
  1244. * unused units removed from uses clause
  1245. * some changes for widestrings
  1246. Revision 1.7 2000/11/16 15:27:48 jonas
  1247. * fixed web bug 1242
  1248. Revision 1.6 2000/11/13 11:30:56 florian
  1249. * some bugs with interfaces and NIL fixed
  1250. Revision 1.5 2000/11/12 23:24:14 florian
  1251. * interfaces are basically running
  1252. Revision 1.4 2000/11/11 16:00:10 jonas
  1253. * optimize converting of 8/16/32 bit constants to 64bit ones
  1254. Revision 1.3 2000/11/04 14:25:23 florian
  1255. + merged Attila's changes for interfaces, not tested yet
  1256. Revision 1.2 2000/10/31 22:02:56 peter
  1257. * symtable splitted, no real code changes
  1258. Revision 1.1 2000/10/15 09:33:31 peter
  1259. * moved n386*.pas to i386/ cpu_target dir
  1260. Revision 1.1 2000/10/14 10:14:48 peter
  1261. * moehrendorf oct 2000 rewrite
  1262. }