cg386cnv.pas 57 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574
  1. {
  2. $Id$
  3. Copyright (c) 1993-98 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. {$ifdef TP}
  19. {$E+,F+,N+,D+,L+,Y+}
  20. {$endif}
  21. unit cg386cnv;
  22. interface
  23. uses
  24. tree;
  25. procedure loadshortstring(p:ptree);
  26. procedure loadansi2short(source,dest : ptree);
  27. procedure secondtypeconv(var p : ptree);
  28. procedure secondas(var p : ptree);
  29. procedure secondis(var p : ptree);
  30. implementation
  31. uses
  32. cobjects,verbose,globtype,globals,systems,
  33. symtable,aasm,types,
  34. hcodegen,temp_gen,pass_2,pass_1,
  35. i386base,i386asm,
  36. cgai386,tgeni386;
  37. procedure push_shortstring_length(p:ptree);
  38. var
  39. hightree : ptree;
  40. begin
  41. if is_open_string(p^.resulttype) then
  42. begin
  43. getsymonlyin(p^.symtable,'high'+pvarsym(p^.symtableentry)^.name);
  44. hightree:=genloadnode(pvarsym(srsym),p^.symtable);
  45. firstpass(hightree);
  46. secondpass(hightree);
  47. push_value_para(hightree,false,0,4);
  48. disposetree(hightree);
  49. end
  50. else
  51. begin
  52. push_int(pstringdef(p^.resulttype)^.len);
  53. end;
  54. end;
  55. procedure loadshortstring(p:ptree);
  56. {
  57. Load a string, handles stringdef and orddef (char) types
  58. }
  59. begin
  60. case p^.right^.resulttype^.deftype of
  61. stringdef:
  62. begin
  63. if (p^.right^.treetype=stringconstn) and
  64. (str_length(p^.right)=0) then
  65. exprasmlist^.concat(new(pai386,op_const_ref(
  66. A_MOV,S_B,0,newreference(p^.left^.location.reference))))
  67. else
  68. begin
  69. emitpushreferenceaddr(p^.left^.location.reference);
  70. emitpushreferenceaddr(p^.right^.location.reference);
  71. push_shortstring_length(p^.left);
  72. emitcall('FPC_SHORTSTR_COPY');
  73. maybe_loadesi;
  74. end;
  75. end;
  76. orddef:
  77. begin
  78. if p^.right^.treetype=ordconstn then
  79. exprasmlist^.concat(new(pai386,op_const_ref(
  80. A_MOV,S_W,p^.right^.value*256+1,newreference(p^.left^.location.reference))))
  81. else
  82. begin
  83. { not so elegant (goes better with extra register }
  84. if (p^.right^.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
  85. begin
  86. exprasmlist^.concat(new(pai386,op_reg_reg(
  87. A_MOV,S_L,makereg32(p^.right^.location.register),R_EDI)));
  88. ungetregister(p^.right^.location.register);
  89. end
  90. else
  91. begin
  92. exprasmlist^.concat(new(pai386,op_ref_reg(
  93. A_MOV,S_L,newreference(p^.right^.location.reference),R_EDI)));
  94. del_reference(p^.right^.location.reference);
  95. end;
  96. exprasmlist^.concat(new(pai386,op_const_reg(A_SHL,S_L,8,R_EDI)));
  97. exprasmlist^.concat(new(pai386,op_const_reg(A_OR,S_L,1,R_EDI)));
  98. exprasmlist^.concat(new(pai386,op_reg_ref(
  99. A_MOV,S_W,R_DI,newreference(p^.left^.location.reference))));
  100. end;
  101. end;
  102. else
  103. CGMessage(type_e_mismatch);
  104. end;
  105. end;
  106. procedure loadansi2short(source,dest : ptree);
  107. var
  108. pushed : tpushed;
  109. begin
  110. del_reference(dest^.location.reference);
  111. case source^.location.loc of
  112. LOC_REFERENCE,LOC_MEM:
  113. begin
  114. ungetiftemp(source^.location.reference);
  115. {$IfNDef regallocfix}
  116. del_reference(source^.location.reference);
  117. pushusedregisters(pushed,$ff);
  118. emit_push_mem(source^.location.reference);
  119. {$Else regallocfix}
  120. pushusedregisters(pushed,$ff
  121. xor ($80 shr byte(source^.location.reference.base))
  122. xor ($80 shr byte(source^.location.reference.index)));
  123. emit_push_mem(source^.location.reference);
  124. del_reference(source^.location.reference);
  125. {$EndIf regallocfix}
  126. end;
  127. LOC_REGISTER,LOC_CREGISTER:
  128. begin
  129. {$IfNDef regallocfix}
  130. ungetregister32(source^.location.register);
  131. pushusedregisters(pushed,$ff);
  132. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,source^.location.register)));
  133. {$Else regallocfix}
  134. pushusedregisters(pushed, $ff xor ($80 shr byte(source^.location.register)));
  135. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,source^.location.register)));
  136. ungetregister32(source^.location.register);
  137. {$EndIf regallocfix}
  138. end;
  139. end;
  140. push_shortstring_length(dest);
  141. emitpushreferenceaddr(dest^.location.reference);
  142. emitcall('FPC_ANSISTR_TO_SHORTSTR');
  143. popusedregisters(pushed);
  144. maybe_loadesi;
  145. end;
  146. {*****************************************************************************
  147. SecondTypeConv
  148. *****************************************************************************}
  149. type
  150. tsecondconvproc = procedure(pto,pfrom : ptree;convtyp : tconverttype);
  151. procedure second_int_to_int(pto,pfrom : ptree;convtyp : tconverttype);
  152. var
  153. op : tasmop;
  154. opsize : topsize;
  155. hregister : tregister;
  156. begin
  157. { insert range check if not explicit conversion }
  158. if not(pto^.explizit) then
  159. emitrangecheck(pfrom,pto^.resulttype);
  160. { is the result size smaller ? }
  161. if pto^.resulttype^.size<pfrom^.resulttype^.size then
  162. begin
  163. { only need to set the new size of a register }
  164. if (pfrom^.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
  165. begin
  166. case pto^.resulttype^.size of
  167. 1 : pto^.location.register:=makereg8(pfrom^.location.register);
  168. 2 : pto^.location.register:=makereg16(pfrom^.location.register);
  169. 4 : pto^.location.register:=makereg32(pfrom^.location.register);
  170. end;
  171. end;
  172. end
  173. { is the result size bigger ? }
  174. else if pto^.resulttype^.size>pfrom^.resulttype^.size then
  175. begin
  176. { remove reference }
  177. if not(pfrom^.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
  178. begin
  179. del_reference(pfrom^.location.reference);
  180. { we can do this here as we need no temp inside }
  181. ungetiftemp(pfrom^.location.reference);
  182. end;
  183. { get op and opsize, handle separate for constants, becuase
  184. movz doesn't support constant values }
  185. if (pfrom^.location.loc=LOC_MEM) and (pfrom^.location.reference.is_immediate) then
  186. begin
  187. opsize:=def_opsize(pto^.resulttype);
  188. op:=A_MOV;
  189. end
  190. else
  191. begin
  192. opsize:=def2def_opsize(pfrom^.resulttype,pto^.resulttype);
  193. if opsize in [S_B,S_W,S_L] then
  194. op:=A_MOV
  195. else
  196. if is_signed(pfrom^.resulttype) then
  197. op:=A_MOVSX
  198. else
  199. op:=A_MOVZX;
  200. end;
  201. { load the register we need }
  202. if pfrom^.location.loc<>LOC_REGISTER then
  203. hregister:=getregister32
  204. else
  205. hregister:=pfrom^.location.register;
  206. { set the correct register size and location }
  207. clear_location(pto^.location);
  208. pto^.location.loc:=LOC_REGISTER;
  209. case pto^.resulttype^.size of
  210. 1 : pto^.location.register:=makereg8(hregister);
  211. 2 : pto^.location.register:=makereg16(hregister);
  212. 4 : pto^.location.register:=makereg32(hregister);
  213. end;
  214. { insert the assembler code }
  215. if pfrom^.location.loc in [LOC_CREGISTER,LOC_REGISTER] then
  216. emit_reg_reg(op,opsize,pfrom^.location.register,pto^.location.register)
  217. else
  218. exprasmlist^.concat(new(pai386,op_ref_reg(op,opsize,
  219. newreference(pfrom^.location.reference),pto^.location.register)));
  220. end;
  221. end;
  222. procedure second_string_to_string(pto,pfrom : ptree;convtyp : tconverttype);
  223. var
  224. pushed : tpushed;
  225. begin
  226. { does anybody know a better solution than this big case statement ? }
  227. { ok, a proc table would do the job }
  228. case pstringdef(pto^.resulttype)^.string_typ of
  229. st_shortstring:
  230. case pstringdef(pfrom^.resulttype)^.string_typ of
  231. st_shortstring:
  232. begin
  233. gettempofsizereference(pto^.resulttype^.size,pto^.location.reference);
  234. del_reference(pfrom^.location.reference);
  235. copyshortstring(pto^.location.reference,pfrom^.location.reference,
  236. pstringdef(pto^.resulttype)^.len,false);
  237. ungetiftemp(pfrom^.location.reference);
  238. end;
  239. st_longstring:
  240. begin
  241. {!!!!!!!}
  242. internalerror(8888);
  243. end;
  244. st_ansistring:
  245. begin
  246. gettempofsizereference(pto^.resulttype^.size,pto^.location.reference);
  247. loadansi2short(pfrom,pto);
  248. { this is done in secondtypeconv (FK)
  249. removetemps(exprasmlist,temptoremove);
  250. destroys:=true;
  251. }
  252. end;
  253. st_widestring:
  254. begin
  255. {!!!!!!!}
  256. internalerror(8888);
  257. end;
  258. end;
  259. st_longstring:
  260. case pstringdef(pfrom^.resulttype)^.string_typ of
  261. st_shortstring:
  262. begin
  263. {!!!!!!!}
  264. internalerror(8888);
  265. end;
  266. st_ansistring:
  267. begin
  268. {!!!!!!!}
  269. internalerror(8888);
  270. end;
  271. st_widestring:
  272. begin
  273. {!!!!!!!}
  274. internalerror(8888);
  275. end;
  276. end;
  277. st_ansistring:
  278. case pstringdef(pfrom^.resulttype)^.string_typ of
  279. st_shortstring:
  280. begin
  281. clear_location(pto^.location);
  282. pto^.location.loc:=LOC_REFERENCE;
  283. gettempansistringreference(pto^.location.reference);
  284. pushusedregisters(pushed,$ff);
  285. emit_push_lea_loc(pfrom^.location);
  286. emit_push_lea_loc(pto^.location);
  287. emitcall('FPC_SHORTSTR_TO_ANSISTR');
  288. maybe_loadesi;
  289. popusedregisters(pushed);
  290. ungetiftemp(pfrom^.location.reference);
  291. end;
  292. st_longstring:
  293. begin
  294. {!!!!!!!}
  295. internalerror(8888);
  296. end;
  297. st_widestring:
  298. begin
  299. {!!!!!!!}
  300. internalerror(8888);
  301. end;
  302. end;
  303. st_widestring:
  304. case pstringdef(pfrom^.resulttype)^.string_typ of
  305. st_shortstring:
  306. begin
  307. {!!!!!!!}
  308. internalerror(8888);
  309. end;
  310. st_longstring:
  311. begin
  312. {!!!!!!!}
  313. internalerror(8888);
  314. end;
  315. st_ansistring:
  316. begin
  317. {!!!!!!!}
  318. internalerror(8888);
  319. end;
  320. st_widestring:
  321. begin
  322. {!!!!!!!}
  323. internalerror(8888);
  324. end;
  325. end;
  326. end;
  327. end;
  328. procedure second_cstring_to_pchar(pto,pfrom : ptree;convtyp : tconverttype);
  329. begin
  330. clear_location(pto^.location);
  331. pto^.location.loc:=LOC_REGISTER;
  332. pto^.location.register:=getregister32;
  333. case pstringdef(pfrom^.resulttype)^.string_typ of
  334. st_shortstring :
  335. begin
  336. inc(pfrom^.location.reference.offset);
  337. exprasmlist^.concat(new(pai386,op_ref_reg(A_LEA,S_L,newreference(pfrom^.location.reference),
  338. pto^.location.register)));
  339. end;
  340. st_ansistring :
  341. begin
  342. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,newreference(pfrom^.location.reference),
  343. pto^.location.register)));
  344. end;
  345. st_longstring:
  346. begin
  347. {!!!!!!!}
  348. internalerror(8888);
  349. end;
  350. st_widestring:
  351. begin
  352. {!!!!!!!}
  353. internalerror(8888);
  354. end;
  355. end;
  356. end;
  357. procedure second_string_to_chararray(pto,pfrom : ptree;convtyp : tconverttype);
  358. begin
  359. case pstringdef(pfrom^.resulttype)^.string_typ of
  360. st_shortstring :
  361. begin
  362. inc(pto^.location.reference.offset);
  363. end;
  364. st_ansistring :
  365. begin
  366. {!!!!!!!}
  367. internalerror(8888);
  368. end;
  369. st_longstring:
  370. begin
  371. {!!!!!!!}
  372. internalerror(8888);
  373. end;
  374. st_widestring:
  375. begin
  376. {!!!!!!!}
  377. internalerror(8888);
  378. end;
  379. end;
  380. end;
  381. procedure second_array_to_pointer(pto,pfrom : ptree;convtyp : tconverttype);
  382. begin
  383. del_reference(pfrom^.location.reference);
  384. clear_location(pto^.location);
  385. pto^.location.loc:=LOC_REGISTER;
  386. pto^.location.register:=getregister32;
  387. exprasmlist^.concat(new(pai386,op_ref_reg(A_LEA,S_L,newreference(pfrom^.location.reference),
  388. pto^.location.register)));
  389. end;
  390. procedure second_pointer_to_array(pto,pfrom : ptree;convtyp : tconverttype);
  391. begin
  392. clear_location(pto^.location);
  393. pto^.location.loc:=LOC_REFERENCE;
  394. reset_reference(pto^.location.reference);
  395. case pfrom^.location.loc of
  396. LOC_REGISTER :
  397. pto^.location.reference.base:=pfrom^.location.register;
  398. LOC_CREGISTER :
  399. begin
  400. pto^.location.reference.base:=getregister32;
  401. emit_reg_reg(A_MOV,S_L,pfrom^.location.register,pto^.location.reference.base);
  402. end
  403. else
  404. begin
  405. del_reference(pfrom^.location.reference);
  406. pto^.location.reference.base:=getregister32;
  407. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,newreference(pfrom^.location.reference),
  408. pto^.location.reference.base)));
  409. end;
  410. end;
  411. end;
  412. { generates the code for the type conversion from an array of char }
  413. { to a string }
  414. procedure second_chararray_to_string(pto,pfrom : ptree;convtyp : tconverttype);
  415. var
  416. pushed : tpushed;
  417. l : longint;
  418. begin
  419. { calc the length of the array }
  420. l:=parraydef(pfrom^.resulttype)^.highrange-parraydef(pfrom^.resulttype)^.lowrange+1;
  421. { this is a type conversion which copies the data, so we can't }
  422. { return a reference }
  423. clear_location(pto^.location);
  424. pto^.location.loc:=LOC_MEM;
  425. case pstringdef(pto^.resulttype)^.string_typ of
  426. st_shortstring :
  427. begin
  428. if l>255 then
  429. begin
  430. CGMessage(type_e_mismatch);
  431. l:=255;
  432. end;
  433. { first get the memory for the string }
  434. gettempofsizereference(256,pto^.location.reference);
  435. { write the length }
  436. exprasmlist^.concat(new(pai386,op_const_ref(A_MOV,S_B,l,
  437. newreference(pto^.location.reference))));
  438. { copy to first char of string }
  439. inc(pto^.location.reference.offset);
  440. { generates the copy code }
  441. { and we need the source never }
  442. concatcopy(pfrom^.location.reference,pto^.location.reference,l,true,false);
  443. { correct the string location }
  444. dec(pto^.location.reference.offset);
  445. end;
  446. st_ansistring :
  447. begin
  448. gettempansistringreference(pto^.location.reference);
  449. release_loc(pfrom^.location);
  450. pushusedregisters(pushed,$ff);
  451. push_int(l);
  452. emitpushreferenceaddr(pfrom^.location.reference);
  453. emitpushreferenceaddr(pto^.location.reference);
  454. emitcall('FPC_CHARARRAY_TO_ANSISTR');
  455. popusedregisters(pushed);
  456. maybe_loadesi;
  457. end;
  458. st_longstring:
  459. begin
  460. {!!!!!!!}
  461. internalerror(8888);
  462. end;
  463. st_widestring:
  464. begin
  465. {!!!!!!!}
  466. internalerror(8888);
  467. end;
  468. end;
  469. end;
  470. procedure second_char_to_string(pto,pfrom : ptree;convtyp : tconverttype);
  471. var
  472. pushed : tpushed;
  473. begin
  474. clear_location(pto^.location);
  475. pto^.location.loc:=LOC_MEM;
  476. case pstringdef(pto^.resulttype)^.string_typ of
  477. st_shortstring :
  478. begin
  479. gettempofsizereference(256,pto^.location.reference);
  480. { call loadstring with correct left and right }
  481. pto^.right:=pfrom;
  482. pto^.left:=pto;
  483. loadshortstring(pto);
  484. pto^.left:=nil; { reset left tree, which is empty }
  485. { pto^.right is not disposed for typeconv !! PM }
  486. disposetree(pto^.right);
  487. pto^.right:=nil;
  488. end;
  489. st_ansistring :
  490. begin
  491. gettempansistringreference(pto^.location.reference);
  492. release_loc(pfrom^.location);
  493. pushusedregisters(pushed,$ff);
  494. emit_pushw_loc(pfrom^.location);
  495. emitpushreferenceaddr(pto^.location.reference);
  496. emitcall('FPC_CHAR_TO_ANSISTR');
  497. popusedregisters(pushed);
  498. maybe_loadesi;
  499. end;
  500. else
  501. internalerror(4179);
  502. end;
  503. end;
  504. procedure second_int_to_real(pto,pfrom : ptree;convtyp : tconverttype);
  505. var
  506. r : preference;
  507. hregister : tregister;
  508. begin
  509. { for u32bit a solution is to push $0 and to load a comp }
  510. { does this first, it destroys maybe EDI }
  511. hregister:=R_EDI;
  512. if porddef(pfrom^.resulttype)^.typ=u32bit then
  513. push_int(0);
  514. if (pfrom^.location.loc=LOC_REGISTER) or
  515. (pfrom^.location.loc=LOC_CREGISTER) then
  516. begin
  517. case porddef(pfrom^.resulttype)^.typ of
  518. s8bit : exprasmlist^.concat(new(pai386,op_reg_reg(A_MOVSX,S_BL,pfrom^.location.register,R_EDI)));
  519. u8bit : exprasmlist^.concat(new(pai386,op_reg_reg(A_MOVZX,S_BL,pfrom^.location.register,R_EDI)));
  520. s16bit : exprasmlist^.concat(new(pai386,op_reg_reg(A_MOVSX,S_WL,pfrom^.location.register,R_EDI)));
  521. u16bit : exprasmlist^.concat(new(pai386,op_reg_reg(A_MOVZX,S_WL,pfrom^.location.register,R_EDI)));
  522. u32bit,s32bit:
  523. hregister:=pfrom^.location.register
  524. end;
  525. ungetregister(pfrom^.location.register);
  526. end
  527. else
  528. begin
  529. r:=newreference(pfrom^.location.reference);
  530. case porddef(pfrom^.resulttype)^.typ of
  531. s8bit : exprasmlist^.concat(new(pai386,op_ref_reg(A_MOVSX,S_BL,r,R_EDI)));
  532. u8bit : exprasmlist^.concat(new(pai386,op_ref_reg(A_MOVZX,S_BL,r,R_EDI)));
  533. s16bit : exprasmlist^.concat(new(pai386,op_ref_reg(A_MOVSX,S_WL,r,R_EDI)));
  534. u16bit : exprasmlist^.concat(new(pai386,op_ref_reg(A_MOVZX,S_WL,r,R_EDI)));
  535. u32bit,s32bit : exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,r,R_EDI)));
  536. end;
  537. del_reference(pfrom^.location.reference);
  538. ungetiftemp(pfrom^.location.reference);
  539. end;
  540. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,hregister)));
  541. r:=new_reference(R_ESP,0);
  542. if porddef(pfrom^.resulttype)^.typ=u32bit then
  543. exprasmlist^.concat(new(pai386,op_ref(A_FILD,S_IQ,r)))
  544. else
  545. exprasmlist^.concat(new(pai386,op_ref(A_FILD,S_IL,r)));
  546. { better than an add on all processors }
  547. if porddef(pfrom^.resulttype)^.typ=u32bit then
  548. exprasmlist^.concat(new(pai386,op_const_reg(A_ADD,S_L,8,R_ESP)))
  549. else
  550. exprasmlist^.concat(new(pai386,op_reg(A_POP,S_L,R_EDI)));
  551. clear_location(pto^.location);
  552. pto^.location.loc:=LOC_FPU;
  553. end;
  554. procedure second_real_to_fix(pto,pfrom : ptree;convtyp : tconverttype);
  555. var
  556. rreg : tregister;
  557. ref : treference;
  558. begin
  559. { real must be on fpu stack }
  560. if (pfrom^.location.loc<>LOC_FPU) then
  561. exprasmlist^.concat(new(pai386,op_ref(A_FLD,S_FL,newreference(pfrom^.location.reference))));
  562. push_int($1f3f);
  563. push_int(65536);
  564. reset_reference(ref);
  565. ref.base:=R_ESP;
  566. exprasmlist^.concat(new(pai386,op_ref(A_FIMUL,S_IL,newreference(ref))));
  567. ref.offset:=4;
  568. exprasmlist^.concat(new(pai386,op_ref(A_FSTCW,S_NO,newreference(ref))));
  569. ref.offset:=6;
  570. exprasmlist^.concat(new(pai386,op_ref(A_FLDCW,S_NO,newreference(ref))));
  571. ref.offset:=0;
  572. exprasmlist^.concat(new(pai386,op_ref(A_FISTP,S_IL,newreference(ref))));
  573. ref.offset:=4;
  574. exprasmlist^.concat(new(pai386,op_ref(A_FLDCW,S_NO,newreference(ref))));
  575. rreg:=getregister32;
  576. exprasmlist^.concat(new(pai386,op_reg(A_POP,S_L,rreg)));
  577. { better than an add on all processors }
  578. exprasmlist^.concat(new(pai386,op_reg(A_POP,S_L,R_EDI)));
  579. clear_location(pto^.location);
  580. pto^.location.loc:=LOC_REGISTER;
  581. pto^.location.register:=rreg;
  582. end;
  583. procedure second_real_to_real(pto,pfrom : ptree;convtyp : tconverttype);
  584. begin
  585. case pfrom^.location.loc of
  586. LOC_FPU : ;
  587. LOC_MEM,
  588. LOC_REFERENCE:
  589. begin
  590. floatload(pfloatdef(pfrom^.resulttype)^.typ,
  591. pfrom^.location.reference);
  592. { we have to free the reference }
  593. del_reference(pfrom^.location.reference);
  594. end;
  595. end;
  596. clear_location(pto^.location);
  597. pto^.location.loc:=LOC_FPU;
  598. end;
  599. procedure second_fix_to_real(pto,pfrom : ptree;convtyp : tconverttype);
  600. var
  601. popeax,popebx,popecx,popedx : boolean;
  602. startreg : tregister;
  603. hl : pasmlabel;
  604. r : treference;
  605. begin
  606. if (pfrom^.location.loc=LOC_REGISTER) or
  607. (pfrom^.location.loc=LOC_CREGISTER) then
  608. begin
  609. startreg:=pfrom^.location.register;
  610. ungetregister(startreg);
  611. popeax:=(startreg<>R_EAX) and not (R_EAX in unused);
  612. if popeax then
  613. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,R_EAX)));
  614. { mov eax,eax is removed by emit_reg_reg }
  615. emit_reg_reg(A_MOV,S_L,startreg,R_EAX);
  616. end
  617. else
  618. begin
  619. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,newreference(
  620. pfrom^.location.reference),R_EAX)));
  621. del_reference(pfrom^.location.reference);
  622. startreg:=R_NO;
  623. end;
  624. popebx:=(startreg<>R_EBX) and not (R_EBX in unused);
  625. if popebx then
  626. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,R_EBX)));
  627. popecx:=(startreg<>R_ECX) and not (R_ECX in unused);
  628. if popecx then
  629. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,R_ECX)));
  630. popedx:=(startreg<>R_EDX) and not (R_EDX in unused);
  631. if popedx then
  632. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,R_EDX)));
  633. exprasmlist^.concat(new(pai386,op_none(A_CDQ,S_NO)));
  634. emit_reg_reg(A_XOR,S_L,R_EDX,R_EAX);
  635. emit_reg_reg(A_MOV,S_L,R_EAX,R_EBX);
  636. emit_reg_reg(A_SUB,S_L,R_EDX,R_EAX);
  637. getlabel(hl);
  638. emitjmp(C_Z,hl);
  639. exprasmlist^.concat(new(pai386,op_const_reg(A_RCL,S_L,1,R_EBX)));
  640. emit_reg_reg(A_BSR,S_L,R_EAX,R_EDX);
  641. exprasmlist^.concat(new(pai386,op_const_reg(A_MOV,S_B,32,R_CL)));
  642. emit_reg_reg(A_SUB,S_B,R_DL,R_CL);
  643. emit_reg_reg(A_SHL,S_L,R_CL,R_EAX);
  644. exprasmlist^.concat(new(pai386,op_const_reg(A_ADD,S_W,1007,R_DX)));
  645. exprasmlist^.concat(new(pai386,op_const_reg(A_SHL,S_W,5,R_DX)));
  646. exprasmlist^.concat(new(pai386,op_const_reg_reg(A_SHLD,S_W,11,R_DX,R_BX)));
  647. exprasmlist^.concat(new(pai386,op_const_reg_reg(A_SHLD,S_L,20,R_EAX,R_EBX)));
  648. exprasmlist^.concat(new(pai386,op_const_reg(A_SHL,S_L,20,R_EAX)));
  649. emitlab(hl);
  650. { better than an add on all processors }
  651. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,R_EBX)));
  652. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,R_EAX)));
  653. reset_reference(r);
  654. r.base:=R_ESP;
  655. exprasmlist^.concat(new(pai386,op_ref(A_FLD,S_FL,newreference(r))));
  656. exprasmlist^.concat(new(pai386,op_const_reg(A_ADD,S_L,8,R_ESP)));
  657. if popedx then
  658. exprasmlist^.concat(new(pai386,op_reg(A_POP,S_L,R_EDX)));
  659. if popecx then
  660. exprasmlist^.concat(new(pai386,op_reg(A_POP,S_L,R_ECX)));
  661. if popebx then
  662. exprasmlist^.concat(new(pai386,op_reg(A_POP,S_L,R_EBX)));
  663. if popeax then
  664. exprasmlist^.concat(new(pai386,op_reg(A_POP,S_L,R_EAX)));
  665. clear_location(pto^.location);
  666. pto^.location.loc:=LOC_FPU;
  667. end;
  668. procedure second_int_to_fix(pto,pfrom : ptree;convtyp : tconverttype);
  669. var
  670. hregister : tregister;
  671. begin
  672. if (pfrom^.location.loc=LOC_REGISTER) then
  673. hregister:=pfrom^.location.register
  674. else if (pfrom^.location.loc=LOC_CREGISTER) then
  675. hregister:=getregister32
  676. else
  677. begin
  678. del_reference(pfrom^.location.reference);
  679. hregister:=getregister32;
  680. case porddef(pfrom^.resulttype)^.typ of
  681. s8bit : exprasmlist^.concat(new(pai386,op_ref_reg(A_MOVSX,S_BL,newreference(pfrom^.location.reference),
  682. hregister)));
  683. u8bit : exprasmlist^.concat(new(pai386,op_ref_reg(A_MOVZX,S_BL,newreference(pfrom^.location.reference),
  684. hregister)));
  685. s16bit : exprasmlist^.concat(new(pai386,op_ref_reg(A_MOVSX,S_WL,newreference(pfrom^.location.reference),
  686. hregister)));
  687. u16bit : exprasmlist^.concat(new(pai386,op_ref_reg(A_MOVZX,S_WL,newreference(pfrom^.location.reference),
  688. hregister)));
  689. u32bit,s32bit : exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,newreference(pfrom^.location.reference),
  690. hregister)));
  691. {!!!! u32bit }
  692. end;
  693. end;
  694. exprasmlist^.concat(new(pai386,op_const_reg(A_SHL,S_L,16,hregister)));
  695. clear_location(pto^.location);
  696. pto^.location.loc:=LOC_REGISTER;
  697. pto^.location.register:=hregister;
  698. end;
  699. procedure second_proc_to_procvar(pto,pfrom : ptree;convtyp : tconverttype);
  700. begin
  701. { method pointer ? }
  702. if assigned(pfrom^.left) then
  703. begin
  704. set_location(pto^.location,pfrom^.location);
  705. end
  706. else
  707. begin
  708. clear_location(pto^.location);
  709. pto^.location.loc:=LOC_REGISTER;
  710. pto^.location.register:=getregister32;
  711. del_reference(pfrom^.location.reference);
  712. exprasmlist^.concat(new(pai386,op_ref_reg(A_LEA,S_L,
  713. newreference(pfrom^.location.reference),pto^.location.register)));
  714. end;
  715. end;
  716. procedure second_bool_to_int(pto,pfrom : ptree;convtyp : tconverttype);
  717. var
  718. oldtruelabel,oldfalselabel,hlabel : pasmlabel;
  719. hregister : tregister;
  720. newsize,
  721. opsize : topsize;
  722. op : tasmop;
  723. begin
  724. oldtruelabel:=truelabel;
  725. oldfalselabel:=falselabel;
  726. getlabel(truelabel);
  727. getlabel(falselabel);
  728. secondpass(pfrom);
  729. { byte(boolean) or word(wordbool) or longint(longbool) must
  730. be accepted for var parameters }
  731. if (pto^.explizit) and
  732. (pfrom^.resulttype^.size=pto^.resulttype^.size) and
  733. (pfrom^.location.loc in [LOC_REFERENCE,LOC_MEM,LOC_CREGISTER]) then
  734. begin
  735. set_location(pto^.location,pfrom^.location);
  736. freelabel(truelabel);
  737. freelabel(falselabel);
  738. truelabel:=oldtruelabel;
  739. falselabel:=oldfalselabel;
  740. exit;
  741. end;
  742. clear_location(pto^.location);
  743. pto^.location.loc:=LOC_REGISTER;
  744. del_reference(pfrom^.location.reference);
  745. case pfrom^.resulttype^.size of
  746. 1 : begin
  747. case pto^.resulttype^.size of
  748. 1 : opsize:=S_B;
  749. 2 : opsize:=S_BW;
  750. 4 : opsize:=S_BL;
  751. end;
  752. end;
  753. 2 : begin
  754. case pto^.resulttype^.size of
  755. 1 : begin
  756. if pfrom^.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
  757. pfrom^.location.register:=reg16toreg8(pfrom^.location.register);
  758. opsize:=S_B;
  759. end;
  760. 2 : opsize:=S_W;
  761. 4 : opsize:=S_WL;
  762. end;
  763. end;
  764. 4 : begin
  765. case pto^.resulttype^.size of
  766. 1 : begin
  767. if pfrom^.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
  768. pfrom^.location.register:=reg32toreg8(pfrom^.location.register);
  769. opsize:=S_B;
  770. end;
  771. 2 : begin
  772. if pfrom^.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
  773. pfrom^.location.register:=reg32toreg16(pfrom^.location.register);
  774. opsize:=S_W;
  775. end;
  776. 4 : opsize:=S_L;
  777. end;
  778. end;
  779. end;
  780. if opsize in [S_B,S_W,S_L] then
  781. op:=A_MOV
  782. else
  783. if is_signed(pto^.resulttype) then
  784. op:=A_MOVSX
  785. else
  786. op:=A_MOVZX;
  787. hregister:=getregister32;
  788. case pto^.resulttype^.size of
  789. 1 : begin
  790. pto^.location.register:=reg32toreg8(hregister);
  791. newsize:=S_B;
  792. end;
  793. 2 : begin
  794. pto^.location.register:=reg32toreg16(hregister);
  795. newsize:=S_W;
  796. end;
  797. 4 : begin
  798. pto^.location.register:=hregister;
  799. newsize:=S_L;
  800. end;
  801. else
  802. internalerror(10060);
  803. end;
  804. case pfrom^.location.loc of
  805. LOC_MEM,
  806. LOC_REFERENCE : exprasmlist^.concat(new(pai386,op_ref_reg(op,opsize,
  807. newreference(pfrom^.location.reference),pto^.location.register)));
  808. LOC_REGISTER,
  809. LOC_CREGISTER : begin
  810. { remove things like movb %al,%al }
  811. if pfrom^.location.register<>pto^.location.register then
  812. exprasmlist^.concat(new(pai386,op_reg_reg(op,opsize,
  813. pfrom^.location.register,pto^.location.register)));
  814. end;
  815. LOC_FLAGS : begin
  816. emit_flag2reg(pfrom^.location.resflags,pto^.location.register);
  817. end;
  818. LOC_JUMP : begin
  819. getlabel(hlabel);
  820. emitlab(truelabel);
  821. exprasmlist^.concat(new(pai386,op_const_reg(A_MOV,newsize,1,pto^.location.register)));
  822. emitjmp(C_None,hlabel);
  823. emitlab(falselabel);
  824. exprasmlist^.concat(new(pai386,op_reg_reg(A_XOR,newsize,pto^.location.register,
  825. pto^.location.register)));
  826. emitlab(hlabel);
  827. end;
  828. else
  829. internalerror(10061);
  830. end;
  831. freelabel(truelabel);
  832. freelabel(falselabel);
  833. truelabel:=oldtruelabel;
  834. falselabel:=oldfalselabel;
  835. end;
  836. procedure second_int_to_bool(pto,pfrom : ptree;convtyp : tconverttype);
  837. var
  838. hregister : tregister;
  839. flags : tresflags;
  840. opsize : topsize;
  841. begin
  842. clear_location(pto^.location);
  843. { byte(boolean) or word(wordbool) or longint(longbool) must
  844. be accepted for var parameters }
  845. if (pto^.explizit) and
  846. (pfrom^.resulttype^.size=pto^.resulttype^.size) and
  847. (pfrom^.location.loc in [LOC_REFERENCE,LOC_MEM,LOC_CREGISTER]) then
  848. begin
  849. set_location(pto^.location,pfrom^.location);
  850. exit;
  851. end;
  852. pto^.location.loc:=LOC_REGISTER;
  853. del_reference(pfrom^.location.reference);
  854. opsize:=def_opsize(pfrom^.resulttype);
  855. case pfrom^.location.loc of
  856. LOC_MEM,LOC_REFERENCE :
  857. begin
  858. hregister:=def_getreg(pfrom^.resulttype);
  859. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,opsize,
  860. newreference(pfrom^.location.reference),hregister)));
  861. exprasmlist^.concat(new(pai386,op_reg_reg(A_OR,opsize,hregister,hregister)));
  862. flags:=F_NE;
  863. end;
  864. LOC_FLAGS :
  865. begin
  866. hregister:=getregister32;
  867. flags:=pfrom^.location.resflags;
  868. end;
  869. LOC_REGISTER,LOC_CREGISTER :
  870. begin
  871. hregister:=pfrom^.location.register;
  872. exprasmlist^.concat(new(pai386,op_reg_reg(A_OR,opsize,hregister,hregister)));
  873. flags:=F_NE;
  874. end;
  875. else
  876. internalerror(10062);
  877. end;
  878. case pto^.resulttype^.size of
  879. 1 : pto^.location.register:=makereg8(hregister);
  880. 2 : pto^.location.register:=makereg16(hregister);
  881. 4 : pto^.location.register:=makereg32(hregister);
  882. else
  883. internalerror(10064);
  884. end;
  885. emit_flag2reg(flags,pto^.location.register);
  886. end;
  887. procedure second_load_smallset(pto,pfrom : ptree;convtyp : tconverttype);
  888. var
  889. href : treference;
  890. pushedregs : tpushed;
  891. begin
  892. href.symbol:=nil;
  893. pushusedregisters(pushedregs,$ff);
  894. gettempofsizereference(32,href);
  895. emitpushreferenceaddr(pfrom^.location.reference);
  896. emitpushreferenceaddr(href);
  897. emitcall('FPC_SET_LOAD_SMALL');
  898. maybe_loadesi;
  899. popusedregisters(pushedregs);
  900. clear_location(pto^.location);
  901. pto^.location.loc:=LOC_MEM;
  902. pto^.location.reference:=href;
  903. end;
  904. procedure second_ansistring_to_pchar(pto,pfrom : ptree;convtyp : tconverttype);
  905. var
  906. l1,l2 : pasmlabel;
  907. hr : preference;
  908. begin
  909. clear_location(pto^.location);
  910. pto^.location.loc:=LOC_REGISTER;
  911. getlabel(l1);
  912. getlabel(l2);
  913. case pfrom^.location.loc of
  914. LOC_CREGISTER,LOC_REGISTER:
  915. exprasmlist^.concat(new(pai386,op_const_reg(A_CMP,S_L,0,
  916. pfrom^.location.register)));
  917. LOC_MEM,LOC_REFERENCE:
  918. begin
  919. exprasmlist^.concat(new(pai386,op_const_ref(A_CMP,S_L,0,
  920. newreference(pfrom^.location.reference))));
  921. del_reference(pfrom^.location.reference);
  922. pto^.location.register:=getregister32;
  923. end;
  924. end;
  925. emitjmp(C_Z,l1);
  926. if pfrom^.location.loc in [LOC_MEM,LOC_REFERENCE] then
  927. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,newreference(
  928. pfrom^.location.reference),
  929. pto^.location.register)));
  930. emitjmp(C_None,l2);
  931. emitlab(l1);
  932. new(hr);
  933. reset_reference(hr^);
  934. hr^.symbol:=newasmsymbol('FPC_EMPTYCHAR');
  935. exprasmlist^.concat(new(pai386,op_ref_reg(A_LEA,S_L,hr,
  936. pto^.location.register)));
  937. emitlab(l2);
  938. end;
  939. procedure second_pchar_to_string(pto,pfrom : ptree;convtyp : tconverttype);
  940. var
  941. pushed : tpushed;
  942. begin
  943. case pstringdef(pto^.resulttype)^.string_typ of
  944. st_shortstring:
  945. begin
  946. pto^.location.loc:=LOC_REFERENCE;
  947. gettempofsizereference(pto^.resulttype^.size,pto^.location.reference);
  948. pushusedregisters(pushed,$ff);
  949. case pfrom^.location.loc of
  950. LOC_REGISTER,LOC_CREGISTER:
  951. begin
  952. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,pfrom^.location.register)));
  953. ungetregister32(pfrom^.location.register);
  954. end;
  955. LOC_REFERENCE,LOC_MEM:
  956. begin
  957. emit_push_mem(pfrom^.location.reference);
  958. del_reference(pfrom^.location.reference);
  959. end;
  960. end;
  961. emitpushreferenceaddr(pto^.location.reference);
  962. emitcall('FPC_PCHAR_TO_SHORTSTR');
  963. maybe_loadesi;
  964. popusedregisters(pushed);
  965. end;
  966. st_ansistring:
  967. begin
  968. pto^.location.loc:=LOC_REFERENCE;
  969. gettempansistringreference(pto^.location.reference);
  970. case pfrom^.location.loc of
  971. LOC_REFERENCE,LOC_MEM:
  972. begin
  973. {$IfNDef regallocfix}
  974. del_reference(pfrom^.location.reference);
  975. pushusedregisters(pushed,$ff);
  976. emit_push_mem(pfrom^.location.reference);
  977. {$Else regallocfix}
  978. pushusedregisters(pushed,$ff
  979. xor ($80 shr byte(pfrom^.location.reference.base))
  980. xor ($80 shr byte(pfrom^.location.reference.index)));
  981. emit_push_mem(pfrom^.location.reference);
  982. del_reference(pfrom^.location.reference);
  983. {$EndIf regallocfix}
  984. end;
  985. LOC_REGISTER,LOC_CREGISTER:
  986. begin
  987. {$IfNDef regallocfix}
  988. ungetregister32(pfrom^.location.register);
  989. pushusedregisters(pushed,$ff);
  990. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,pfrom^.location.register)));
  991. {$Else regallocfix}
  992. pushusedregisters(pushed, $ff xor ($80 shr byte(pfrom^.location.register)));
  993. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,pfrom^.location.register)));
  994. ungetregister32(pfrom^.location.register);
  995. {$EndIf regallocfix}
  996. end;
  997. end;
  998. emitpushreferenceaddr(pto^.location.reference);
  999. emitcall('FPC_PCHAR_TO_ANSISTR');
  1000. maybe_loadesi;
  1001. popusedregisters(pushed);
  1002. end;
  1003. else
  1004. begin
  1005. internalerror(12121);
  1006. end;
  1007. end;
  1008. end;
  1009. procedure second_nothing(pto,pfrom : ptree;convtyp : tconverttype);
  1010. begin
  1011. end;
  1012. {****************************************************************************
  1013. SecondTypeConv
  1014. ****************************************************************************}
  1015. procedure secondtypeconv(var p : ptree);
  1016. const
  1017. secondconvert : array[tconverttype] of tsecondconvproc = (
  1018. second_nothing, {equal}
  1019. second_nothing, {not_possible}
  1020. second_string_to_string,
  1021. second_char_to_string,
  1022. second_pchar_to_string,
  1023. second_nothing, {cchar_to_pchar}
  1024. second_cstring_to_pchar,
  1025. second_ansistring_to_pchar,
  1026. second_string_to_chararray,
  1027. second_chararray_to_string,
  1028. second_array_to_pointer,
  1029. second_pointer_to_array,
  1030. second_int_to_int,
  1031. second_int_to_bool,
  1032. second_bool_to_int, { bool_to_bool }
  1033. second_bool_to_int,
  1034. second_real_to_real,
  1035. second_int_to_real,
  1036. second_int_to_fix,
  1037. second_real_to_fix,
  1038. second_fix_to_real,
  1039. second_proc_to_procvar,
  1040. second_nothing, {arrayconstructor_to_set}
  1041. second_load_smallset
  1042. );
  1043. {$ifdef TESTOBJEXT2}
  1044. var
  1045. r : preference;
  1046. nillabel : plabel;
  1047. {$endif TESTOBJEXT2}
  1048. begin
  1049. { this isn't good coding, I think tc_bool_2_int, shouldn't be }
  1050. { type conversion (FK) }
  1051. if not(p^.convtyp in [tc_bool_2_int,tc_bool_2_bool]) then
  1052. begin
  1053. secondpass(p^.left);
  1054. set_location(p^.location,p^.left^.location);
  1055. if codegenerror then
  1056. exit;
  1057. end;
  1058. { the second argument only is for maybe_range_checking !}
  1059. secondconvert[p^.convtyp](p,p^.left,p^.convtyp);
  1060. {$ifdef TESTOBJEXT2}
  1061. { Check explicit conversions to objects pointers !! }
  1062. if p^.explizit and
  1063. (p^.resulttype^.deftype=pointerdef) and
  1064. (ppointerdef(p^.resulttype)^.definition^.deftype=objectdef) and not
  1065. (pobjectdef(ppointerdef(p^.resulttype)^.definition)^.isclass) and
  1066. ((pobjectdef(ppointerdef(p^.resulttype)^.definition)^.options and oo_hasvmt)<>0) and
  1067. (cs_check_range in aktlocalswitches) then
  1068. begin
  1069. new(r);
  1070. reset_reference(r^);
  1071. if p^.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
  1072. r^.base:=p^.location.register
  1073. else
  1074. begin
  1075. emit_mov_loc_reg(p^.location,R_EDI);
  1076. r^.base:=R_EDI;
  1077. end;
  1078. { NIL must be accepted !! }
  1079. exprasmlist^.concat(new(pai386,op_reg_reg(A_OR,S_L,r^.base,r^.base)));
  1080. getlabel(nillabel);
  1081. emitjmp(C_E,nillabel);
  1082. { this is one point where we need vmt_offset (PM) }
  1083. r^.offset:= pobjectdef(ppointerdef(p^.resulttype)^.definition)^.vmt_offset;
  1084. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,r,R_EDI)));
  1085. exprasmlist^.concat(new(pai386,op_sym(A_PUSH,S_L,
  1086. newasmsymbol(pobjectdef(ppointerdef(p^.resulttype)^.definition)^.vmt_mangledname))));
  1087. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,R_EDI)));
  1088. emitcall('FPC_CHECK_OBJECT_EXT');
  1089. emitlab(nillabel);
  1090. end;
  1091. {$endif TESTOBJEXT2}
  1092. end;
  1093. {*****************************************************************************
  1094. SecondIs
  1095. *****************************************************************************}
  1096. procedure secondis(var p : ptree);
  1097. var
  1098. pushed : tpushed;
  1099. begin
  1100. { save all used registers }
  1101. pushusedregisters(pushed,$ff);
  1102. secondpass(p^.left);
  1103. clear_location(p^.location);
  1104. p^.location.loc:=LOC_FLAGS;
  1105. p^.location.resflags:=F_NE;
  1106. { push instance to check: }
  1107. case p^.left^.location.loc of
  1108. LOC_REGISTER,LOC_CREGISTER:
  1109. begin
  1110. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,
  1111. S_L,p^.left^.location.register)));
  1112. ungetregister32(p^.left^.location.register);
  1113. end;
  1114. LOC_MEM,LOC_REFERENCE:
  1115. begin
  1116. exprasmlist^.concat(new(pai386,op_ref(A_PUSH,
  1117. S_L,newreference(p^.left^.location.reference))));
  1118. del_reference(p^.left^.location.reference);
  1119. end;
  1120. else internalerror(100);
  1121. end;
  1122. { generate type checking }
  1123. secondpass(p^.right);
  1124. case p^.right^.location.loc of
  1125. LOC_REGISTER,LOC_CREGISTER:
  1126. begin
  1127. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,
  1128. S_L,p^.right^.location.register)));
  1129. ungetregister32(p^.right^.location.register);
  1130. end;
  1131. LOC_MEM,LOC_REFERENCE:
  1132. begin
  1133. exprasmlist^.concat(new(pai386,op_ref(A_PUSH,
  1134. S_L,newreference(p^.right^.location.reference))));
  1135. del_reference(p^.right^.location.reference);
  1136. end;
  1137. else internalerror(100);
  1138. end;
  1139. emitcall('FPC_DO_IS');
  1140. exprasmlist^.concat(new(pai386,op_reg_reg(A_OR,S_B,R_AL,R_AL)));
  1141. popusedregisters(pushed);
  1142. maybe_loadesi;
  1143. end;
  1144. {*****************************************************************************
  1145. SecondAs
  1146. *****************************************************************************}
  1147. procedure secondas(var p : ptree);
  1148. var
  1149. pushed : tpushed;
  1150. begin
  1151. secondpass(p^.left);
  1152. { save all used registers }
  1153. pushusedregisters(pushed,$ff);
  1154. { push instance to check: }
  1155. case p^.left^.location.loc of
  1156. LOC_REGISTER,LOC_CREGISTER:
  1157. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,
  1158. S_L,p^.left^.location.register)));
  1159. LOC_MEM,LOC_REFERENCE:
  1160. exprasmlist^.concat(new(pai386,op_ref(A_PUSH,
  1161. S_L,newreference(p^.left^.location.reference))));
  1162. else internalerror(100);
  1163. end;
  1164. { we doesn't modifiy the left side, we check only the type }
  1165. set_location(p^.location,p^.left^.location);
  1166. { generate type checking }
  1167. secondpass(p^.right);
  1168. case p^.right^.location.loc of
  1169. LOC_REGISTER,LOC_CREGISTER:
  1170. begin
  1171. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,
  1172. S_L,p^.right^.location.register)));
  1173. ungetregister32(p^.right^.location.register);
  1174. end;
  1175. LOC_MEM,LOC_REFERENCE:
  1176. begin
  1177. exprasmlist^.concat(new(pai386,op_ref(A_PUSH,
  1178. S_L,newreference(p^.right^.location.reference))));
  1179. del_reference(p^.right^.location.reference);
  1180. end;
  1181. else internalerror(100);
  1182. end;
  1183. emitcall('FPC_DO_AS');
  1184. { restore register, this restores automatically the }
  1185. { result }
  1186. popusedregisters(pushed);
  1187. end;
  1188. end.
  1189. {
  1190. $Log$
  1191. Revision 1.74 1999-05-27 19:44:09 peter
  1192. * removed oldasm
  1193. * plabel -> pasmlabel
  1194. * -a switches to source writing automaticly
  1195. * assembler readers OOPed
  1196. * asmsymbol automaticly external
  1197. * jumptables and other label fixes for asm readers
  1198. Revision 1.73 1999/05/18 21:58:26 florian
  1199. * fixed some bugs related to temp. ansistrings and functions results
  1200. which return records/objects/arrays which need init/final.
  1201. Revision 1.72 1999/05/17 21:57:00 florian
  1202. * new temporary ansistring handling
  1203. Revision 1.71 1999/05/12 00:19:40 peter
  1204. * removed R_DEFAULT_SEG
  1205. * uniform float names
  1206. Revision 1.70 1999/05/07 00:33:47 pierre
  1207. explicit type conv to pobject checked with cond TESTOBJEXT2
  1208. Revision 1.69 1999/05/01 13:24:04 peter
  1209. * merged nasm compiler
  1210. * old asm moved to oldasm/
  1211. Revision 1.68 1999/04/28 06:01:54 florian
  1212. * changes of Bruessel:
  1213. + message handler can now take an explicit self
  1214. * typinfo fixed: sometimes the type names weren't written
  1215. * the type checking for pointer comparisations and subtraction
  1216. and are now more strict (was also buggy)
  1217. * small bug fix to link.pas to support compiling on another
  1218. drive
  1219. * probable bug in popt386 fixed: call/jmp => push/jmp
  1220. transformation didn't count correctly the jmp references
  1221. + threadvar support
  1222. * warning if ln/sqrt gets an invalid constant argument
  1223. Revision 1.67 1999/04/22 10:49:07 peter
  1224. * fixed pchar to string location
  1225. Revision 1.66 1999/04/20 10:35:58 peter
  1226. * fixed bool2bool
  1227. Revision 1.65 1999/04/19 09:45:47 pierre
  1228. + cdecl or stdcall push all args with longint size
  1229. * tempansi stuff cleaned up
  1230. Revision 1.64 1999/04/16 13:42:25 jonas
  1231. * more regalloc fixes (still not complete)
  1232. Revision 1.63 1999/04/15 08:56:25 peter
  1233. * fixed bool-bool conversion
  1234. Revision 1.62 1999/04/13 18:51:47 florian
  1235. * esi wasn't reloaded after a call to the esi helper procedure, fixed
  1236. Revision 1.61 1999/03/05 16:14:20 peter
  1237. * fixed boolean() typecast
  1238. Revision 1.60 1999/03/02 18:24:19 peter
  1239. * fixed overloading of array of char
  1240. Revision 1.59 1999/03/01 15:46:18 peter
  1241. * ag386bin finally make cycles correct
  1242. * prefixes are now also normal opcodes
  1243. Revision 1.58 1999/02/25 21:02:23 peter
  1244. * ag386bin updates
  1245. + coff writer
  1246. Revision 1.57 1999/02/22 02:15:06 peter
  1247. * updates for ag386bin
  1248. Revision 1.56 1999/02/15 11:30:39 pierre
  1249. * memory leaks removed
  1250. Revision 1.55 1999/02/12 10:43:57 florian
  1251. * internal error 10 with ansistrings fixed
  1252. Revision 1.54 1999/02/02 12:35:02 florian
  1253. * ltemptoremove handling corrected
  1254. Revision 1.53 1999/02/02 11:47:55 peter
  1255. * fixed ansi2short
  1256. Revision 1.52 1999/01/29 11:22:13 pierre
  1257. * saving and restoring old ltemptoremove
  1258. Revision 1.51 1999/01/28 19:50:15 peter
  1259. * removed warning
  1260. Revision 1.50 1999/01/28 14:06:45 florian
  1261. * small fix for method pointers
  1262. * found the annoying strpas bug, mainly nested call to type cast which
  1263. use ansistrings crash
  1264. Revision 1.49 1999/01/27 14:56:56 pierre
  1265. * typo error corrected solves bug0190 and bug0204
  1266. Revision 1.48 1999/01/27 13:03:27 pierre
  1267. boolean to int conversion problems bug0205 bug0208
  1268. Revision 1.47 1999/01/27 12:59:32 pierre
  1269. wrong commit info : tccnv.pas
  1270. Revision 1.46 1999/01/27 00:13:53 florian
  1271. * "procedure of object"-stuff fixed
  1272. Revision 1.45 1999/01/21 22:10:36 peter
  1273. * fixed array of const
  1274. * generic platform independent high() support
  1275. Revision 1.44 1999/01/19 10:18:59 florian
  1276. * bug with mul. of dwords fixed, reported by Alexander Stohr
  1277. * some changes to compile with TP
  1278. + small enhancements for the new code generator
  1279. Revision 1.43 1998/12/22 13:10:59 florian
  1280. * memory leaks for ansistring type casts fixed
  1281. Revision 1.42 1998/12/19 00:23:42 florian
  1282. * ansistring memory leaks fixed
  1283. Revision 1.41 1998/11/30 19:48:54 peter
  1284. * some more rangecheck fixes
  1285. Revision 1.40 1998/11/30 09:43:02 pierre
  1286. * some range check bugs fixed (still not working !)
  1287. + added DLL writing support for win32 (also accepts variables)
  1288. + TempAnsi for code that could be used for Temporary ansi strings
  1289. handling
  1290. Revision 1.39 1998/11/29 22:37:30 peter
  1291. * fixed constant ansistring -> pchar
  1292. Revision 1.38 1998/11/29 12:40:19 peter
  1293. * newcnv -> not oldcnv
  1294. Revision 1.37 1998/11/26 21:33:06 peter
  1295. * rangecheck updates
  1296. Revision 1.36 1998/11/26 14:39:11 peter
  1297. * ansistring -> pchar fixed
  1298. * ansistring constants fixed
  1299. * ansistring constants are now written once
  1300. Revision 1.35 1998/11/26 13:10:39 peter
  1301. * new int - int conversion -dNEWCNV
  1302. * some function renamings
  1303. Revision 1.34 1998/11/18 15:44:08 peter
  1304. * VALUEPARA for tp7 compatible value parameters
  1305. Revision 1.33 1998/11/17 00:36:39 peter
  1306. * more ansistring fixes
  1307. Revision 1.32 1998/11/16 15:35:38 peter
  1308. * rename laod/copystring -> load/copyshortstring
  1309. * fixed int-bool cnv bug
  1310. + char-ansistring conversion
  1311. Revision 1.31 1998/11/05 12:02:30 peter
  1312. * released useansistring
  1313. * removed -Sv, its now available in fpc modes
  1314. Revision 1.30 1998/10/27 11:12:45 peter
  1315. * fixed char_to_string which did not set the .loc
  1316. Revision 1.29 1998/10/26 15:18:41 peter
  1317. * fixed fldcw,fstcw for as 2.9.1
  1318. Revision 1.28 1998/10/08 17:17:11 pierre
  1319. * current_module old scanner tagged as invalid if unit is recompiled
  1320. + added ppheap for better info on tracegetmem of heaptrc
  1321. (adds line column and file index)
  1322. * several memory leaks removed ith help of heaptrc !!
  1323. Revision 1.27 1998/10/06 17:16:40 pierre
  1324. * some memory leaks fixed (thanks to Peter for heaptrc !)
  1325. Revision 1.26 1998/10/02 07:20:35 florian
  1326. * range checking in units doesn't work if the units are smartlinked, fixed
  1327. Revision 1.25 1998/09/30 12:14:24 peter
  1328. * fixed boolean(longbool) conversion
  1329. Revision 1.24 1998/09/27 10:16:22 florian
  1330. * type casts pchar<->ansistring fixed
  1331. * ansistring[..] calls does now an unique call
  1332. Revision 1.23 1998/09/23 12:03:51 peter
  1333. * overloading fix for array of const
  1334. Revision 1.22 1998/09/22 15:34:09 peter
  1335. + pchar -> string conversion
  1336. Revision 1.21 1998/09/20 17:46:47 florian
  1337. * some things regarding ansistrings fixed
  1338. Revision 1.20 1998/09/17 09:42:12 peter
  1339. + pass_2 for cg386
  1340. * Message() -> CGMessage() for pass_1/pass_2
  1341. Revision 1.19 1998/09/14 10:43:46 peter
  1342. * all internal RTL functions start with FPC_
  1343. Revision 1.18 1998/09/11 12:29:40 pierre
  1344. * removed explicit range_checking as it is buggy
  1345. Revision 1.17.2.1 1998/09/11 12:08:54 pierre
  1346. * removed explicit range_check was buggy
  1347. Revision 1.17 1998/09/04 08:41:38 peter
  1348. * updated some error CGMessages
  1349. Revision 1.16 1998/09/03 17:39:03 florian
  1350. + better code for type conversation longint/dword to real type
  1351. Revision 1.15 1998/09/03 16:24:50 florian
  1352. * bug of type conversation from dword to real fixed
  1353. * bug fix of Jonas applied
  1354. Revision 1.14 1998/08/28 12:51:39 florian
  1355. + ansistring to pchar type cast fixed
  1356. Revision 1.13 1998/08/28 10:56:56 peter
  1357. * removed warnings
  1358. Revision 1.12 1998/08/14 18:18:38 peter
  1359. + dynamic set contruction
  1360. * smallsets are now working (always longint size)
  1361. Revision 1.11 1998/08/10 23:59:59 peter
  1362. * fixed dup log
  1363. Revision 1.10 1998/08/10 14:49:47 peter
  1364. + localswitches, moduleswitches, globalswitches splitting
  1365. Revision 1.9 1998/08/05 16:00:09 florian
  1366. * some fixes for ansi strings
  1367. Revision 1.8 1998/07/18 22:54:24 florian
  1368. * some ansi/wide/longstring support fixed:
  1369. o parameter passing
  1370. o returning as result from functions
  1371. Revision 1.7 1998/06/12 13:10:34 peter
  1372. * small internalerror nr change
  1373. Revision 1.6 1998/06/12 10:43:12 michael
  1374. Fixed ansistrings : is_ansistring not found
  1375. Revision 1.5 1998/06/08 13:13:30 pierre
  1376. + temporary variables now in temp_gen.pas unit
  1377. because it is processor independent
  1378. * mppc68k.bat modified to undefine i386 and support_mmx
  1379. (which are defaults for i386)
  1380. Revision 1.4 1998/06/05 17:44:10 peter
  1381. * splitted cgi386
  1382. Revision 1.3 1998/06/03 22:48:50 peter
  1383. + wordbool,longbool
  1384. * rename bis,von -> high,low
  1385. * moved some systemunit loading/creating to psystem.pas
  1386. Revision 1.2 1998/06/02 10:52:10 peter
  1387. * fixed second_bool_to_int with bool8bit return
  1388. Revision 1.1 1998/06/01 16:50:18 peter
  1389. + boolean -> ord conversion
  1390. * fixed ord -> boolean conversion
  1391. }