cg386cnv.pas 55 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436
  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 secondtypeconv(var p : ptree);
  26. procedure secondas(var p : ptree);
  27. procedure secondis(var p : ptree);
  28. implementation
  29. uses
  30. cobjects,verbose,globals,systems,
  31. symtable,aasm,types,
  32. hcodegen,temp_gen,pass_2,
  33. i386,cgai386,tgeni386;
  34. {*****************************************************************************
  35. SecondTypeConv
  36. *****************************************************************************}
  37. procedure maybe_rangechecking(p : ptree;p2,p1 : pdef);
  38. {
  39. produces if necessary rangecheckcode
  40. }
  41. var
  42. hp : preference;
  43. hregister : tregister;
  44. neglabel,poslabel : plabel;
  45. is_register : boolean;
  46. begin
  47. { convert from p2 to p1 }
  48. { range check from enums is not made yet !!}
  49. { and its probably not easy }
  50. if (p1^.deftype<>orddef) or (p2^.deftype<>orddef) then
  51. exit;
  52. { range checking is different for u32bit }
  53. { lets try to generate it allways }
  54. if (cs_check_range in aktlocalswitches) and
  55. { with $R+ explicit type conversations in TP aren't range checked! }
  56. (not(p^.explizit) {or not(cs_tp_compatible in aktmoduleswitches)}) and
  57. ((porddef(p1)^.low>porddef(p2)^.low) or
  58. (porddef(p1)^.high<porddef(p2)^.high) or
  59. (porddef(p1)^.typ=u32bit) or
  60. (porddef(p2)^.typ=u32bit)) then
  61. begin
  62. porddef(p1)^.genrangecheck;
  63. is_register:=(p^.left^.location.loc=LOC_REGISTER) or
  64. (p^.left^.location.loc=LOC_CREGISTER);
  65. if porddef(p2)^.typ=u8bit then
  66. begin
  67. if is_register then
  68. exprasmlist^.concat(new(pai386,op_reg_reg(A_MOVZX,S_BL,p^.left^.location.register,R_EDI)))
  69. else
  70. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOVZX,S_BL,newreference(p^.left^.location.reference),R_EDI)));
  71. hregister:=R_EDI;
  72. end
  73. else if porddef(p2)^.typ=s8bit then
  74. begin
  75. if is_register then
  76. exprasmlist^.concat(new(pai386,op_reg_reg(A_MOVSX,S_BL,p^.left^.location.register,R_EDI)))
  77. else
  78. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOVSX,S_BL,newreference(p^.left^.location.reference),R_EDI)));
  79. hregister:=R_EDI;
  80. end
  81. { rangechecking for u32bit ?? !!!!!!}
  82. { lets try }
  83. else if (porddef(p2)^.typ=s32bit) or (porddef(p2)^.typ=u32bit) then
  84. begin
  85. if is_register then
  86. hregister:=p^.location.register
  87. else
  88. begin
  89. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,newreference(p^.left^.location.reference),R_EDI)));
  90. hregister:=R_EDI;
  91. end;
  92. end
  93. else if porddef(p2)^.typ=u16bit then
  94. begin
  95. if is_register then
  96. exprasmlist^.concat(new(pai386,op_reg_reg(A_MOVZX,S_WL,p^.left^.location.register,R_EDI)))
  97. else
  98. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOVZX,S_WL,newreference(p^.left^.location.reference),R_EDI)));
  99. hregister:=R_EDI;
  100. end
  101. else if porddef(p2)^.typ=s16bit then
  102. begin
  103. if is_register then
  104. exprasmlist^.concat(new(pai386,op_reg_reg(A_MOVSX,S_WL,p^.left^.location.register,R_EDI)))
  105. else
  106. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOVSX,S_WL,newreference(p^.left^.location.reference),R_EDI)));
  107. hregister:=R_EDI;
  108. end
  109. else internalerror(6);
  110. hp:=new_reference(R_NO,0);
  111. hp^.symbol:=stringdup(porddef(p1)^.getrangecheckstring);
  112. if porddef(p1)^.low>porddef(p1)^.high then
  113. begin
  114. getlabel(neglabel);
  115. getlabel(poslabel);
  116. exprasmlist^.concat(new(pai386,op_reg_reg(A_OR,S_L,hregister,hregister)));
  117. emitl(A_JL,neglabel);
  118. end;
  119. exprasmlist^.concat(new(pai386,op_reg_ref(A_BOUND,S_L,hregister,hp)));
  120. if porddef(p1)^.low>porddef(p1)^.high then
  121. begin
  122. hp:=new_reference(R_NO,0);
  123. hp^.symbol:=stringdup(porddef(p1)^.getrangecheckstring);
  124. emitl(A_JMP,poslabel);
  125. emitl(A_LABEL,neglabel);
  126. exprasmlist^.concat(new(pai386,op_reg_ref(A_BOUND,S_L,hregister,hp)));
  127. emitl(A_LABEL,poslabel);
  128. end;
  129. end;
  130. end;
  131. type
  132. tsecondconvproc = procedure(p,hp : ptree;convtyp : tconverttype);
  133. procedure second_only_rangecheck(p,hp : ptree;convtyp : tconverttype);
  134. begin
  135. maybe_rangechecking(p,hp^.resulttype,p^.resulttype);
  136. end;
  137. procedure second_smaller(p,hp : ptree;convtyp : tconverttype);
  138. var
  139. hregister,destregister : tregister;
  140. ref : boolean;
  141. hpp : preference;
  142. begin
  143. ref:=false;
  144. { problems with enums !! }
  145. if (cs_check_range in aktlocalswitches) and
  146. { with $R+ explicit type conversations in TP aren't range checked! }
  147. (not(p^.explizit) {or not(cs_tp_compatible in aktmoduleswitches)}) and
  148. (p^.resulttype^.deftype=orddef) and
  149. (hp^.resulttype^.deftype=orddef) then
  150. begin
  151. if porddef(hp^.resulttype)^.typ=u32bit then
  152. begin
  153. { when doing range checking for u32bit, we have some trouble }
  154. { because BOUND assumes signed values }
  155. { first, we check if the values is greater than 2^31: }
  156. { the u32bit rangenr contains the appropriate rangenr }
  157. porddef(hp^.resulttype)^.genrangecheck;
  158. hregister:=R_EDI;
  159. if (p^.location.loc=LOC_REGISTER) or
  160. (p^.location.loc=LOC_CREGISTER) then
  161. hregister:=p^.location.register
  162. else
  163. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,
  164. newreference(p^.location.reference),R_EDI)));
  165. hpp:=new_reference(R_NO,0);
  166. hpp^.symbol:=stringdup(porddef(hp^.resulttype)^.getrangecheckstring);
  167. exprasmlist^.concat(new(pai386,op_reg_ref(A_BOUND,S_L,hregister,hpp)));
  168. { then we do a normal range check }
  169. porddef(p^.resulttype)^.genrangecheck;
  170. hpp:=new_reference(R_NO,0);
  171. hpp^.symbol:=stringdup(porddef(p^.resulttype)^.getrangecheckstring);
  172. exprasmlist^.concat(new(pai386,op_reg_ref(A_BOUND,S_L,hregister,hpp)));
  173. end
  174. else
  175. if ((porddef(p^.resulttype)^.low>porddef(hp^.resulttype)^.low) or
  176. (porddef(p^.resulttype)^.high<porddef(hp^.resulttype)^.high)) then
  177. begin
  178. porddef(p^.resulttype)^.genrangecheck;
  179. { per default the var is copied to EDI }
  180. hregister:=R_EDI;
  181. if porddef(hp^.resulttype)^.typ=s32bit then
  182. begin
  183. if (p^.location.loc=LOC_REGISTER) or
  184. (p^.location.loc=LOC_CREGISTER) then
  185. hregister:=p^.location.register
  186. else
  187. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,newreference(p^.location.reference),R_EDI)));
  188. end
  189. else if porddef(hp^.resulttype)^.typ=u16bit then
  190. begin
  191. if (p^.location.loc=LOC_REGISTER) or
  192. (p^.location.loc=LOC_CREGISTER) then
  193. exprasmlist^.concat(new(pai386,op_reg_reg(A_MOVZX,S_WL,p^.location.register,R_EDI)))
  194. else
  195. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOVZX,S_WL,newreference(p^.location.reference),R_EDI)));
  196. end
  197. else if porddef(hp^.resulttype)^.typ=s16bit then
  198. begin
  199. if (p^.location.loc=LOC_REGISTER) or
  200. (p^.location.loc=LOC_CREGISTER) then
  201. exprasmlist^.concat(new(pai386,op_reg_reg(A_MOVSX,S_WL,p^.location.register,R_EDI)))
  202. else
  203. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOVSX,S_WL,newreference(p^.location.reference),R_EDI)));
  204. end
  205. else internalerror(6);
  206. hpp:=new_reference(R_NO,0);
  207. hpp^.symbol:=stringdup(porddef(p^.resulttype)^.getrangecheckstring);
  208. exprasmlist^.concat(new(pai386,op_reg_ref(A_BOUND,S_L,hregister,hpp)));
  209. (*
  210. if (p^.location.loc=LOC_REGISTER) or
  211. (p^.location.loc=LOC_CREGISTER) then
  212. begin
  213. destregister:=p^.left^.location.register;
  214. case convtyp of
  215. tc_s32bit_2_s8bit,
  216. tc_s32bit_2_u8bit:
  217. destregister:=reg32toreg8(destregister);
  218. tc_s32bit_2_s16bit,
  219. tc_s32bit_2_u16bit:
  220. destregister:=reg32toreg16(destregister);
  221. { this was false because destregister is allways a 32bitreg }
  222. tc_s16bit_2_s8bit,
  223. tc_s16bit_2_u8bit,
  224. tc_u16bit_2_s8bit,
  225. tc_u16bit_2_u8bit:
  226. destregister:=reg32toreg8(destregister);
  227. end;
  228. p^.location.register:=destregister;
  229. exit;
  230. *)
  231. end;
  232. end;
  233. { p^.location.loc is already set! }
  234. if (p^.location.loc=LOC_REGISTER) or
  235. (p^.location.loc=LOC_CREGISTER) then
  236. begin
  237. destregister:=p^.left^.location.register;
  238. case convtyp of
  239. tc_s32bit_2_s8bit,
  240. tc_s32bit_2_u8bit:
  241. destregister:=reg32toreg8(destregister);
  242. tc_s32bit_2_s16bit,
  243. tc_s32bit_2_u16bit:
  244. destregister:=reg32toreg16(destregister);
  245. tc_s16bit_2_s8bit,
  246. tc_s16bit_2_u8bit,
  247. tc_u16bit_2_s8bit,
  248. tc_u16bit_2_u8bit:
  249. destregister:=reg16toreg8(destregister);
  250. end;
  251. p^.location.register:=destregister;
  252. end;
  253. end;
  254. procedure second_bigger(p,hp : ptree;convtyp : tconverttype);
  255. var
  256. hregister : tregister;
  257. opsize : topsize;
  258. op : tasmop;
  259. is_register : boolean;
  260. begin
  261. is_register:=p^.left^.location.loc=LOC_REGISTER;
  262. if not(is_register) and (p^.left^.location.loc<>LOC_CREGISTER) then
  263. begin
  264. del_reference(p^.left^.location.reference);
  265. { we can do this here as we need no temp inside second_bigger }
  266. ungetiftemp(p^.left^.location.reference);
  267. end;
  268. { this is wrong !!!
  269. gives me movl (%eax),%eax
  270. for the length(string !!!
  271. use only for constant values }
  272. {Constant cannot be loaded into registers using MOVZX!}
  273. if (p^.left^.location.loc<>LOC_MEM) or (not p^.left^.location.reference.isintvalue) then
  274. case convtyp of
  275. tc_u8bit_2_s32bit,tc_u8bit_2_u32bit :
  276. begin
  277. if is_register then
  278. hregister:=reg8toreg32(p^.left^.location.register)
  279. else hregister:=getregister32;
  280. op:=A_MOVZX;
  281. opsize:=S_BL;
  282. end;
  283. { here what do we do for negative values ? }
  284. tc_s8bit_2_s32bit,tc_s8bit_2_u32bit :
  285. begin
  286. if is_register then
  287. hregister:=reg8toreg32(p^.left^.location.register)
  288. else hregister:=getregister32;
  289. op:=A_MOVSX;
  290. opsize:=S_BL;
  291. end;
  292. tc_u16bit_2_s32bit,tc_u16bit_2_u32bit :
  293. begin
  294. if is_register then
  295. hregister:=reg16toreg32(p^.left^.location.register)
  296. else hregister:=getregister32;
  297. op:=A_MOVZX;
  298. opsize:=S_WL;
  299. end;
  300. tc_s16bit_2_s32bit,tc_s16bit_2_u32bit :
  301. begin
  302. if is_register then
  303. hregister:=reg16toreg32(p^.left^.location.register)
  304. else hregister:=getregister32;
  305. op:=A_MOVSX;
  306. opsize:=S_WL;
  307. end;
  308. tc_s8bit_2_u16bit,
  309. tc_u8bit_2_s16bit,
  310. tc_u8bit_2_u16bit :
  311. begin
  312. if is_register then
  313. hregister:=reg8toreg16(p^.left^.location.register)
  314. else hregister:=reg32toreg16(getregister32);
  315. op:=A_MOVZX;
  316. opsize:=S_BW;
  317. end;
  318. tc_s8bit_2_s16bit :
  319. begin
  320. if is_register then
  321. hregister:=reg8toreg16(p^.left^.location.register)
  322. else hregister:=reg32toreg16(getregister32);
  323. op:=A_MOVSX;
  324. opsize:=S_BW;
  325. end;
  326. end
  327. else
  328. case convtyp of
  329. tc_u8bit_2_s32bit,
  330. tc_s8bit_2_s32bit,
  331. tc_u16bit_2_s32bit,
  332. tc_s16bit_2_s32bit,
  333. tc_u8bit_2_u32bit,
  334. tc_s8bit_2_u32bit,
  335. tc_u16bit_2_u32bit,
  336. tc_s16bit_2_u32bit:
  337. begin
  338. hregister:=getregister32;
  339. op:=A_MOV;
  340. opsize:=S_L;
  341. end;
  342. tc_s8bit_2_u16bit,
  343. tc_s8bit_2_s16bit,
  344. tc_u8bit_2_s16bit,
  345. tc_u8bit_2_u16bit:
  346. begin
  347. hregister:=reg32toreg16(getregister32);
  348. op:=A_MOV;
  349. opsize:=S_W;
  350. end;
  351. end;
  352. if is_register then
  353. begin
  354. emit_reg_reg(op,opsize,p^.left^.location.register,hregister);
  355. end
  356. else
  357. begin
  358. if p^.left^.location.loc=LOC_CREGISTER then
  359. emit_reg_reg(op,opsize,p^.left^.location.register,hregister)
  360. else exprasmlist^.concat(new(pai386,op_ref_reg(op,opsize,
  361. newreference(p^.left^.location.reference),hregister)));
  362. end;
  363. clear_location(p^.location);
  364. p^.location.loc:=LOC_REGISTER;
  365. p^.location.register:=hregister;
  366. maybe_rangechecking(p,p^.left^.resulttype,p^.resulttype);
  367. end;
  368. procedure second_string_string(p,hp : ptree;convtyp : tconverttype);
  369. {$ifdef UseAnsiString}
  370. var
  371. pushed : tpushed;
  372. {$endif UseAnsiString}
  373. begin
  374. {$ifdef UseAnsiString}
  375. { does anybody know a better solution than this big case statement ? }
  376. { ok, a proc table would do the job }
  377. case pstringdef(p^.resulttype)^.string_typ of
  378. st_shortstring:
  379. case pstringdef(p^.left^.resulttype)^.string_typ of
  380. st_shortstring:
  381. begin
  382. stringdispose(p^.location.reference.symbol);
  383. gettempofsizereference(p^.resulttype^.size,p^.location.reference);
  384. del_reference(p^.left^.location.reference);
  385. copystring(p^.location.reference,p^.left^.location.reference,pstringdef(p^.resulttype)^.len);
  386. ungetiftemp(p^.left^.location.reference);
  387. end;
  388. st_longstring:
  389. begin
  390. {!!!!!!!}
  391. internalerror(8888);
  392. end;
  393. st_ansistring:
  394. begin
  395. gettempofsizereference(p^.resulttype^.size,p^.location.reference);
  396. loadansi2short(p^.left,p);
  397. end;
  398. st_widestring:
  399. begin
  400. {!!!!!!!}
  401. internalerror(8888);
  402. end;
  403. end;
  404. st_longstring:
  405. case pstringdef(p^.left)^.string_typ of
  406. st_shortstring:
  407. begin
  408. {!!!!!!!}
  409. internalerror(8888);
  410. end;
  411. st_ansistring:
  412. begin
  413. {!!!!!!!}
  414. internalerror(8888);
  415. end;
  416. st_widestring:
  417. begin
  418. {!!!!!!!}
  419. internalerror(8888);
  420. end;
  421. end;
  422. st_ansistring:
  423. case pstringdef(p^.left)^.string_typ of
  424. st_shortstring:
  425. begin
  426. pushusedregisters(pushed,$ff);
  427. gettempofsizereference(p^.resulttype^.size,p^.location.reference);
  428. emitpushreferenceaddr(exprasmlist,p^.location.reference);
  429. case p^.left^.location.loc of
  430. LOC_REGISTER,LOC_CREGISTER:
  431. begin
  432. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,p^.left^.location.register)));
  433. ungetregister32(p^.left^.location.register);
  434. end;
  435. LOC_REFERENCE,LOC_MEM:
  436. begin
  437. emit_push_mem(p^.left^.location.reference);
  438. del_reference(p^.left^.location.reference);
  439. end;
  440. end;
  441. emitcall('FPC_ANSI_TO_SHORTSTRING',true);
  442. maybe_loadesi;
  443. popusedregisters(pushed);
  444. end;
  445. st_longstring:
  446. begin
  447. {!!!!!!!}
  448. internalerror(8888);
  449. end;
  450. st_widestring:
  451. begin
  452. {!!!!!!!}
  453. internalerror(8888);
  454. end;
  455. end;
  456. st_widestring:
  457. case pstringdef(p^.left)^.string_typ of
  458. st_shortstring:
  459. begin
  460. {!!!!!!!}
  461. internalerror(8888);
  462. end;
  463. st_longstring:
  464. begin
  465. {!!!!!!!}
  466. internalerror(8888);
  467. end;
  468. st_ansistring:
  469. begin
  470. {!!!!!!!}
  471. internalerror(8888);
  472. end;
  473. st_widestring:
  474. begin
  475. {!!!!!!!}
  476. internalerror(8888);
  477. end;
  478. end;
  479. end;
  480. {$ifdef dummy}
  481. if is_ansistring(p^.resulttype) and not is_ansistring(p^.left^.resulttype) then
  482. begin
  483. { call shortstring to ansistring conversion }
  484. { result is in register }
  485. del_reference(p^.left^.location.reference);
  486. {!!!!
  487. copyshortstringtoansistring(p^.location,p^.left^.location.reference,pstringdef(p^.resulttype)^.len);
  488. }
  489. ungetiftemp(p^.left^.location.reference);
  490. end
  491. else if not is_ansistring(p^.resulttype) and is_ansistring(p^.left^.resulttype) then
  492. begin
  493. { call ansistring to shortstring conversion }
  494. { result is in mem }
  495. stringdispose(p^.location.reference.symbol);
  496. gettempofsizereference(p^.resulttype^.size,p^.location.reference);
  497. if p^.left^.location.loc in [LOC_MEM,LOC_REFERENCE] then
  498. del_reference(p^.left^.location.reference);
  499. copyansistringtoshortstring(p^.location.reference,p^.left^.location.reference,pstringdef(p^.resulttype)^.len);
  500. ungetiftemp(p^.left^.location.reference);
  501. end
  502. else
  503. {$endif dummy}
  504. {$else UseAnsiString}
  505. begin
  506. stringdispose(p^.location.reference.symbol);
  507. gettempofsizereference(p^.resulttype^.size,p^.location.reference);
  508. del_reference(p^.left^.location.reference);
  509. copystring(p^.location.reference,p^.left^.location.reference,pstringdef(p^.resulttype)^.len);
  510. ungetiftemp(p^.left^.location.reference);
  511. end;
  512. {$endif UseAnsiString}
  513. end;
  514. procedure second_cstring_charpointer(p,hp : ptree;convtyp : tconverttype);
  515. begin
  516. clear_location(p^.location);
  517. p^.location.loc:=LOC_REGISTER;
  518. p^.location.register:=getregister32;
  519. inc(p^.left^.location.reference.offset);
  520. exprasmlist^.concat(new(pai386,op_ref_reg(A_LEA,S_L,newreference(p^.left^.location.reference),
  521. p^.location.register)));
  522. end;
  523. procedure second_string_chararray(p,hp : ptree;convtyp : tconverttype);
  524. begin
  525. inc(p^.location.reference.offset);
  526. end;
  527. procedure second_array_to_pointer(p,hp : ptree;convtyp : tconverttype);
  528. begin
  529. del_reference(p^.left^.location.reference);
  530. clear_location(p^.location);
  531. p^.location.loc:=LOC_REGISTER;
  532. p^.location.register:=getregister32;
  533. exprasmlist^.concat(new(pai386,op_ref_reg(A_LEA,S_L,newreference(p^.left^.location.reference),
  534. p^.location.register)));
  535. end;
  536. procedure second_pointer_to_array(p,hp : ptree;convtyp : tconverttype);
  537. begin
  538. clear_location(p^.location);
  539. p^.location.loc:=LOC_REFERENCE;
  540. clear_reference(p^.location.reference);
  541. if p^.left^.location.loc=LOC_REGISTER then
  542. p^.location.reference.base:=p^.left^.location.register
  543. else
  544. begin
  545. if p^.left^.location.loc=LOC_CREGISTER then
  546. begin
  547. p^.location.reference.base:=getregister32;
  548. emit_reg_reg(A_MOV,S_L,p^.left^.location.register,
  549. p^.location.reference.base);
  550. end
  551. else
  552. begin
  553. del_reference(p^.left^.location.reference);
  554. p^.location.reference.base:=getregister32;
  555. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,newreference(p^.left^.location.reference),
  556. p^.location.reference.base)));
  557. end;
  558. end;
  559. end;
  560. { generates the code for the type conversion from an array of char }
  561. { to a string }
  562. procedure second_chararray_to_string(p,hp : ptree;convtyp : tconverttype);
  563. var
  564. l : longint;
  565. begin
  566. { this is a type conversion which copies the data, so we can't }
  567. { return a reference }
  568. clear_location(p^.location);
  569. p^.location.loc:=LOC_MEM;
  570. { first get the memory for the string }
  571. stringdispose(p^.location.reference.symbol);
  572. gettempofsizereference(256,p^.location.reference);
  573. { calc the length of the array }
  574. l:=parraydef(p^.left^.resulttype)^.highrange-
  575. parraydef(p^.left^.resulttype)^.lowrange+1;
  576. if l>255 then
  577. CGMessage(type_e_mismatch);
  578. { write the length }
  579. exprasmlist^.concat(new(pai386,op_const_ref(A_MOV,S_B,l,
  580. newreference(p^.location.reference))));
  581. { copy to first char of string }
  582. inc(p^.location.reference.offset);
  583. { generates the copy code }
  584. { and we need the source never }
  585. concatcopy(p^.left^.location.reference,p^.location.reference,l,true);
  586. { correct the string location }
  587. dec(p^.location.reference.offset);
  588. end;
  589. procedure second_char_to_string(p,hp : ptree;convtyp : tconverttype);
  590. begin
  591. stringdispose(p^.location.reference.symbol);
  592. gettempofsizereference(256,p^.location.reference);
  593. { call loadstring with correct left and right }
  594. p^.right:=p^.left;
  595. p^.left:=p;
  596. loadstring(p);
  597. p^.left:=nil; { reset left tree, which is empty }
  598. { p^.right is not disposed for typeconv !! PM }
  599. disposetree(p^.right);
  600. p^.right:=nil;
  601. end;
  602. procedure second_int_real(p,hp : ptree;convtyp : tconverttype);
  603. var
  604. r : preference;
  605. hregister : tregister;
  606. begin
  607. { for u32bit a solution is to push $0 and to load a comp }
  608. { does this first, it destroys maybe EDI }
  609. hregister:=R_EDI;
  610. if porddef(p^.left^.resulttype)^.typ=u32bit then
  611. push_int(0);
  612. if (p^.left^.location.loc=LOC_REGISTER) or
  613. (p^.left^.location.loc=LOC_CREGISTER) then
  614. begin
  615. case porddef(p^.left^.resulttype)^.typ of
  616. s8bit : exprasmlist^.concat(new(pai386,op_reg_reg(A_MOVSX,S_BL,p^.left^.location.register,R_EDI)));
  617. u8bit : exprasmlist^.concat(new(pai386,op_reg_reg(A_MOVZX,S_BL,p^.left^.location.register,R_EDI)));
  618. s16bit : exprasmlist^.concat(new(pai386,op_reg_reg(A_MOVSX,S_WL,p^.left^.location.register,R_EDI)));
  619. u16bit : exprasmlist^.concat(new(pai386,op_reg_reg(A_MOVZX,S_WL,p^.left^.location.register,R_EDI)));
  620. u32bit,s32bit:
  621. hregister:=p^.left^.location.register
  622. end;
  623. ungetregister(p^.left^.location.register);
  624. end
  625. else
  626. begin
  627. r:=newreference(p^.left^.location.reference);
  628. case porddef(p^.left^.resulttype)^.typ of
  629. s8bit : exprasmlist^.concat(new(pai386,op_ref_reg(A_MOVSX,S_BL,r,R_EDI)));
  630. u8bit : exprasmlist^.concat(new(pai386,op_ref_reg(A_MOVZX,S_BL,r,R_EDI)));
  631. s16bit : exprasmlist^.concat(new(pai386,op_ref_reg(A_MOVSX,S_WL,r,R_EDI)));
  632. u16bit : exprasmlist^.concat(new(pai386,op_ref_reg(A_MOVZX,S_WL,r,R_EDI)));
  633. u32bit,s32bit : exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,r,R_EDI)));
  634. end;
  635. del_reference(p^.left^.location.reference);
  636. ungetiftemp(p^.left^.location.reference);
  637. end;
  638. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,hregister)));
  639. r:=new_reference(R_ESP,0);
  640. if porddef(p^.left^.resulttype)^.typ=u32bit then
  641. exprasmlist^.concat(new(pai386,op_ref(A_FILD,S_IQ,r)))
  642. else
  643. exprasmlist^.concat(new(pai386,op_ref(A_FILD,S_IL,r)));
  644. { better than an add on all processors }
  645. if porddef(p^.left^.resulttype)^.typ=u32bit then
  646. exprasmlist^.concat(new(pai386,op_const_reg(A_ADD,S_L,8,R_ESP)))
  647. else
  648. exprasmlist^.concat(new(pai386,op_reg(A_POP,S_L,R_EDI)));
  649. clear_location(p^.location);
  650. p^.location.loc:=LOC_FPU;
  651. end;
  652. procedure second_real_fix(p,hp : ptree;convtyp : tconverttype);
  653. var
  654. {hs : string;}
  655. rreg : tregister;
  656. ref : treference;
  657. begin
  658. { real must be on fpu stack }
  659. if (p^.left^.location.loc<>LOC_FPU) then
  660. exprasmlist^.concat(new(pai386,op_ref(A_FLD,S_FL,newreference(p^.left^.location.reference))));
  661. push_int($1f3f);
  662. push_int(65536);
  663. reset_reference(ref);
  664. ref.base:=R_ESP;
  665. exprasmlist^.concat(new(pai386,op_ref(A_FIMUL,S_IL,newreference(ref))));
  666. ref.offset:=4;
  667. exprasmlist^.concat(new(pai386,op_ref(A_FSTCW,S_L,newreference(ref))));
  668. ref.offset:=6;
  669. exprasmlist^.concat(new(pai386,op_ref(A_FLDCW,S_L,newreference(ref))));
  670. ref.offset:=0;
  671. exprasmlist^.concat(new(pai386,op_ref(A_FISTP,S_IL,newreference(ref))));
  672. ref.offset:=4;
  673. exprasmlist^.concat(new(pai386,op_ref(A_FLDCW,S_L,newreference(ref))));
  674. rreg:=getregister32;
  675. exprasmlist^.concat(new(pai386,op_reg(A_POP,S_L,rreg)));
  676. { better than an add on all processors }
  677. exprasmlist^.concat(new(pai386,op_reg(A_POP,S_L,R_EDI)));
  678. clear_location(p^.location);
  679. p^.location.loc:=LOC_REGISTER;
  680. p^.location.register:=rreg;
  681. end;
  682. procedure second_float_float(p,hp : ptree;convtyp : tconverttype);
  683. begin
  684. case p^.left^.location.loc of
  685. LOC_FPU : ;
  686. LOC_MEM,
  687. LOC_REFERENCE:
  688. begin
  689. floatload(pfloatdef(p^.left^.resulttype)^.typ,
  690. p^.left^.location.reference);
  691. { we have to free the reference }
  692. del_reference(p^.left^.location.reference);
  693. end;
  694. end;
  695. clear_location(p^.location);
  696. p^.location.loc:=LOC_FPU;
  697. end;
  698. procedure second_fix_real(p,hp : ptree;convtyp : tconverttype);
  699. var popeax,popebx,popecx,popedx : boolean;
  700. startreg : tregister;
  701. hl : plabel;
  702. r : treference;
  703. begin
  704. if (p^.left^.location.loc=LOC_REGISTER) or
  705. (p^.left^.location.loc=LOC_CREGISTER) then
  706. begin
  707. startreg:=p^.left^.location.register;
  708. ungetregister(startreg);
  709. popeax:=(startreg<>R_EAX) and not (R_EAX in unused);
  710. if popeax then
  711. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,R_EAX)));
  712. { mov eax,eax is removed by emit_reg_reg }
  713. emit_reg_reg(A_MOV,S_L,startreg,R_EAX);
  714. end
  715. else
  716. begin
  717. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,newreference(
  718. p^.left^.location.reference),R_EAX)));
  719. del_reference(p^.left^.location.reference);
  720. startreg:=R_NO;
  721. end;
  722. popebx:=(startreg<>R_EBX) and not (R_EBX in unused);
  723. if popebx then
  724. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,R_EBX)));
  725. popecx:=(startreg<>R_ECX) and not (R_ECX in unused);
  726. if popecx then
  727. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,R_ECX)));
  728. popedx:=(startreg<>R_EDX) and not (R_EDX in unused);
  729. if popedx then
  730. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,R_EDX)));
  731. exprasmlist^.concat(new(pai386,op_none(A_CDQ,S_NO)));
  732. emit_reg_reg(A_XOR,S_L,R_EDX,R_EAX);
  733. emit_reg_reg(A_MOV,S_L,R_EAX,R_EBX);
  734. emit_reg_reg(A_SUB,S_L,R_EDX,R_EAX);
  735. getlabel(hl);
  736. emitl(A_JZ,hl);
  737. exprasmlist^.concat(new(pai386,op_const_reg(A_RCL,S_L,1,R_EBX)));
  738. emit_reg_reg(A_BSR,S_L,R_EAX,R_EDX);
  739. exprasmlist^.concat(new(pai386,op_const_reg(A_MOV,S_B,32,R_CL)));
  740. emit_reg_reg(A_SUB,S_B,R_DL,R_CL);
  741. emit_reg_reg(A_SHL,S_L,R_CL,R_EAX);
  742. exprasmlist^.concat(new(pai386,op_const_reg(A_ADD,S_W,1007,R_DX)));
  743. exprasmlist^.concat(new(pai386,op_const_reg(A_SHL,S_W,5,R_DX)));
  744. exprasmlist^.concat(new(pai386,op_const_reg_reg(A_SHLD,S_W,11,R_DX,R_BX)));
  745. exprasmlist^.concat(new(pai386,op_const_reg_reg(A_SHLD,S_W,20,R_EAX,R_EBX)));
  746. exprasmlist^.concat(new(pai386,op_const_reg(A_SHL,S_L,20,R_EAX)));
  747. emitl(A_LABEL,hl);
  748. { better than an add on all processors }
  749. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,R_EBX)));
  750. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,R_EAX)));
  751. reset_reference(r);
  752. r.base:=R_ESP;
  753. exprasmlist^.concat(new(pai386,op_ref(A_FLD,S_FL,newreference(r))));
  754. exprasmlist^.concat(new(pai386,op_const_reg(A_ADD,S_L,8,R_ESP)));
  755. if popedx then
  756. exprasmlist^.concat(new(pai386,op_reg(A_POP,S_L,R_EDX)));
  757. if popecx then
  758. exprasmlist^.concat(new(pai386,op_reg(A_POP,S_L,R_ECX)));
  759. if popebx then
  760. exprasmlist^.concat(new(pai386,op_reg(A_POP,S_L,R_EBX)));
  761. if popeax then
  762. exprasmlist^.concat(new(pai386,op_reg(A_POP,S_L,R_EAX)));
  763. clear_location(p^.location);
  764. p^.location.loc:=LOC_FPU;
  765. end;
  766. procedure second_int_fix(p,hp : ptree;convtyp : tconverttype);
  767. var
  768. {hs : string;}
  769. hregister : tregister;
  770. begin
  771. if (p^.left^.location.loc=LOC_REGISTER) then
  772. hregister:=p^.left^.location.register
  773. else if (p^.left^.location.loc=LOC_CREGISTER) then
  774. hregister:=getregister32
  775. else
  776. begin
  777. del_reference(p^.left^.location.reference);
  778. hregister:=getregister32;
  779. case porddef(p^.left^.resulttype)^.typ of
  780. s8bit : exprasmlist^.concat(new(pai386,op_ref_reg(A_MOVSX,S_BL,newreference(p^.left^.location.reference),
  781. hregister)));
  782. u8bit : exprasmlist^.concat(new(pai386,op_ref_reg(A_MOVZX,S_BL,newreference(p^.left^.location.reference),
  783. hregister)));
  784. s16bit : exprasmlist^.concat(new(pai386,op_ref_reg(A_MOVSX,S_WL,newreference(p^.left^.location.reference),
  785. hregister)));
  786. u16bit : exprasmlist^.concat(new(pai386,op_ref_reg(A_MOVZX,S_WL,newreference(p^.left^.location.reference),
  787. hregister)));
  788. u32bit,s32bit : exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,newreference(p^.left^.location.reference),
  789. hregister)));
  790. {!!!! u32bit }
  791. end;
  792. end;
  793. exprasmlist^.concat(new(pai386,op_const_reg(A_SHL,S_L,16,hregister)));
  794. clear_location(p^.location);
  795. p^.location.loc:=LOC_REGISTER;
  796. p^.location.register:=hregister;
  797. end;
  798. procedure second_proc_to_procvar(p,hp : ptree;convtyp : tconverttype);
  799. begin
  800. clear_location(p^.location);
  801. p^.location.loc:=LOC_REGISTER;
  802. del_reference(hp^.location.reference);
  803. p^.location.register:=getregister32;
  804. exprasmlist^.concat(new(pai386,op_ref_reg(A_LEA,S_L,
  805. newreference(hp^.location.reference),p^.location.register)));
  806. end;
  807. procedure second_bool_to_int(p,hp : ptree;convtyp : tconverttype);
  808. var
  809. oldtruelabel,oldfalselabel,hlabel : plabel;
  810. hregister : tregister;
  811. newsize,
  812. opsize : topsize;
  813. op : tasmop;
  814. begin
  815. oldtruelabel:=truelabel;
  816. oldfalselabel:=falselabel;
  817. getlabel(truelabel);
  818. getlabel(falselabel);
  819. secondpass(hp);
  820. clear_location(p^.location);
  821. p^.location.loc:=LOC_REGISTER;
  822. del_reference(hp^.location.reference);
  823. case hp^.resulttype^.size of
  824. 1 : begin
  825. case p^.resulttype^.size of
  826. 1 : opsize:=S_B;
  827. 2 : opsize:=S_BW;
  828. 4 : opsize:=S_BL;
  829. end;
  830. end;
  831. 2 : begin
  832. case p^.resulttype^.size of
  833. 1 : begin
  834. if hp^.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
  835. hp^.location.register:=reg16toreg8(hp^.location.register);
  836. opsize:=S_B;
  837. end;
  838. 2 : opsize:=S_W;
  839. 4 : opsize:=S_WL;
  840. end;
  841. end;
  842. 4 : begin
  843. case p^.resulttype^.size of
  844. 1 : begin
  845. if hp^.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
  846. hp^.location.register:=reg32toreg8(hp^.location.register);
  847. opsize:=S_B;
  848. end;
  849. 2 : begin
  850. if hp^.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
  851. hp^.location.register:=reg32toreg16(hp^.location.register);
  852. opsize:=S_W;
  853. end;
  854. 4 : opsize:=S_L;
  855. end;
  856. end;
  857. end;
  858. if opsize in [S_B,S_W,S_L] then
  859. op:=A_MOV
  860. else
  861. if is_signed(p^.resulttype) then
  862. op:=A_MOVSX
  863. else
  864. op:=A_MOVZX;
  865. hregister:=getregister32;
  866. case p^.resulttype^.size of
  867. 1 : begin
  868. p^.location.register:=reg32toreg8(hregister);
  869. newsize:=S_B;
  870. end;
  871. 2 : begin
  872. p^.location.register:=reg32toreg16(hregister);
  873. newsize:=S_W;
  874. end;
  875. 4 : begin
  876. p^.location.register:=hregister;
  877. newsize:=S_L;
  878. end;
  879. else
  880. internalerror(10060);
  881. end;
  882. case hp^.location.loc of
  883. LOC_MEM,
  884. LOC_REFERENCE : exprasmlist^.concat(new(pai386,op_ref_reg(op,opsize,
  885. newreference(hp^.location.reference),p^.location.register)));
  886. LOC_REGISTER,
  887. LOC_CREGISTER : begin
  888. { remove things like movb %al,%al }
  889. if hp^.location.register<>p^.location.register then
  890. exprasmlist^.concat(new(pai386,op_reg_reg(op,opsize,
  891. hp^.location.register,p^.location.register)));
  892. end;
  893. LOC_FLAGS : begin
  894. hregister:=reg32toreg8(hregister);
  895. exprasmlist^.concat(new(pai386,op_reg(flag_2_set[hp^.location.resflags],S_B,hregister)));
  896. case p^.resulttype^.size of
  897. 2 : exprasmlist^.concat(new(pai386,op_reg_reg(A_MOVZX,S_BW,hregister,p^.location.register)));
  898. 4 : exprasmlist^.concat(new(pai386,op_reg_reg(A_MOVZX,S_BL,hregister,p^.location.register)));
  899. end;
  900. end;
  901. LOC_JUMP : begin
  902. getlabel(hlabel);
  903. emitl(A_LABEL,truelabel);
  904. exprasmlist^.concat(new(pai386,op_const_reg(A_MOV,newsize,1,hregister)));
  905. emitl(A_JMP,hlabel);
  906. emitl(A_LABEL,falselabel);
  907. exprasmlist^.concat(new(pai386,op_reg_reg(A_XOR,newsize,hregister,hregister)));
  908. emitl(A_LABEL,hlabel);
  909. end;
  910. else
  911. internalerror(10061);
  912. end;
  913. freelabel(truelabel);
  914. freelabel(falselabel);
  915. truelabel:=oldtruelabel;
  916. falselabel:=oldfalselabel;
  917. end;
  918. procedure second_int_to_bool(p,hp : ptree;convtyp : tconverttype);
  919. var
  920. hregister : tregister;
  921. begin
  922. clear_location(p^.location);
  923. p^.location.loc:=LOC_REGISTER;
  924. del_reference(hp^.location.reference);
  925. case hp^.location.loc of
  926. LOC_MEM,LOC_REFERENCE :
  927. begin
  928. hregister:=getregister32;
  929. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,
  930. newreference(hp^.location.reference),hregister)));
  931. end;
  932. LOC_REGISTER,LOC_CREGISTER :
  933. begin
  934. hregister:=hp^.location.register;
  935. end;
  936. else
  937. internalerror(10062);
  938. end;
  939. exprasmlist^.concat(new(pai386,op_reg_reg(A_OR,S_L,hregister,hregister)));
  940. hregister:=reg32toreg8(hregister);
  941. exprasmlist^.concat(new(pai386,op_reg(flag_2_set[hp^.location.resflags],S_B,hregister)));
  942. case p^.resulttype^.size of
  943. 1 : p^.location.register:=hregister;
  944. 2 : begin
  945. p^.location.register:=reg8toreg16(hregister);
  946. exprasmlist^.concat(new(pai386,op_reg_reg(A_MOVZX,S_BW,hregister,p^.location.register)));
  947. end;
  948. 4 : begin
  949. p^.location.register:=reg16toreg32(hregister);
  950. exprasmlist^.concat(new(pai386,op_reg_reg(A_MOVZX,S_BL,hregister,p^.location.register)));
  951. end;
  952. else
  953. internalerror(10064);
  954. end;
  955. end;
  956. procedure second_load_smallset(p,hp : ptree;convtyp : tconverttype);
  957. var
  958. href : treference;
  959. pushedregs : tpushed;
  960. begin
  961. href.symbol:=nil;
  962. pushusedregisters(pushedregs,$ff);
  963. gettempofsizereference(32,href);
  964. emitpushreferenceaddr(exprasmlist,p^.left^.location.reference);
  965. emitpushreferenceaddr(exprasmlist,href);
  966. emitcall('FPC_SET_LOAD_SMALL',true);
  967. maybe_loadesi;
  968. popusedregisters(pushedregs);
  969. clear_location(p^.location);
  970. p^.location.loc:=LOC_MEM;
  971. p^.location.reference:=href;
  972. end;
  973. procedure second_ansistring_to_pchar(p,hp : ptree;convtyp : tconverttype);
  974. var
  975. l1,l2 : plabel;
  976. hr : preference;
  977. begin
  978. clear_location(p^.location);
  979. p^.location.loc:=LOC_REGISTER;
  980. getlabel(l1);
  981. getlabel(l2);
  982. case hp^.location.loc of
  983. LOC_CREGISTER,LOC_REGISTER:
  984. exprasmlist^.concat(new(pai386,op_const_reg(A_CMP,S_L,0,
  985. hp^.location.register)));
  986. LOC_MEM,LOC_REFERENCE:
  987. begin
  988. exprasmlist^.concat(new(pai386,op_const_ref(A_CMP,S_L,0,
  989. newreference(hp^.location.reference))));
  990. del_reference(hp^.location.reference);
  991. p^.location.register:=getregister32;
  992. end;
  993. end;
  994. emitl(A_JZ,l1);
  995. if hp^.location.loc in [LOC_MEM,LOC_REFERENCE] then
  996. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,newreference(
  997. hp^.location.reference),
  998. p^.location.register)));
  999. emitl(A_JMP,l2);
  1000. emitl(A_LABEL,l1);
  1001. new(hr);
  1002. reset_reference(hr^);
  1003. hr^.symbol:=stringdup('FPC_EMPTYCHAR');
  1004. exprasmlist^.concat(new(pai386,op_ref_reg(A_LEA,S_L,hr,
  1005. p^.location.register)));
  1006. emitl(A_LABEL,l2);
  1007. end;
  1008. procedure second_pchar_to_string(p,hp : ptree;convtyp : tconverttype);
  1009. var
  1010. pushed : tpushed;
  1011. begin
  1012. case pstringdef(p^.resulttype)^.string_typ of
  1013. st_shortstring:
  1014. begin
  1015. pushusedregisters(pushed,$ff);
  1016. stringdispose(p^.location.reference.symbol);
  1017. gettempofsizereference(p^.resulttype^.size,p^.location.reference);
  1018. case p^.left^.location.loc of
  1019. LOC_REGISTER,LOC_CREGISTER:
  1020. begin
  1021. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,p^.left^.location.register)));
  1022. ungetregister32(p^.left^.location.register);
  1023. end;
  1024. LOC_REFERENCE,LOC_MEM:
  1025. begin
  1026. emit_push_mem(p^.left^.location.reference);
  1027. del_reference(p^.left^.location.reference);
  1028. end;
  1029. end;
  1030. emitpushreferenceaddr(exprasmlist,p^.location.reference);
  1031. emitcall('FPC_PCHAR_TO_STR',true);
  1032. maybe_loadesi;
  1033. popusedregisters(pushed);
  1034. end;
  1035. st_ansistring:
  1036. begin
  1037. stringdispose(p^.location.reference.symbol);
  1038. gettempofsizereference(p^.resulttype^.size,p^.location.reference);
  1039. case p^.left^.location.loc of
  1040. LOC_REGISTER,LOC_CREGISTER:
  1041. begin
  1042. ungetregister32(p^.left^.location.register);
  1043. pushusedregisters(pushed,$ff);
  1044. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,p^.left^.location.register)));
  1045. end;
  1046. LOC_REFERENCE,LOC_MEM:
  1047. begin
  1048. del_reference(p^.left^.location.reference);
  1049. pushusedregisters(pushed,$ff);
  1050. emit_push_mem(p^.left^.location.reference);
  1051. end;
  1052. end;
  1053. emitpushreferenceaddr(exprasmlist,p^.location.reference);
  1054. emitcall('FPC_PCHAR_TO_ANSISTRING',true);
  1055. maybe_loadesi;
  1056. popusedregisters(pushed);
  1057. end;
  1058. else
  1059. begin
  1060. clear_location(p^.location);
  1061. p^.location.loc:=LOC_REGISTER;
  1062. internalerror(12121);
  1063. end;
  1064. end;
  1065. end;
  1066. procedure second_nothing(p,hp : ptree;convtyp : tconverttype);
  1067. begin
  1068. end;
  1069. {****************************************************************************
  1070. SecondTypeConv
  1071. ****************************************************************************}
  1072. procedure secondtypeconv(var p : ptree);
  1073. const
  1074. secondconvert : array[tconverttype] of
  1075. tsecondconvproc = (second_nothing,second_nothing,
  1076. second_bigger,second_only_rangecheck,
  1077. second_bigger,second_bigger,second_bigger,
  1078. second_smaller,second_smaller,
  1079. second_smaller,second_string_string,
  1080. second_cstring_charpointer,second_string_chararray,
  1081. second_array_to_pointer,second_pointer_to_array,
  1082. second_char_to_string,second_bigger,
  1083. second_bigger,second_bigger,
  1084. second_smaller,second_smaller,
  1085. second_smaller,second_smaller,
  1086. second_bigger,second_smaller,
  1087. second_only_rangecheck,second_bigger,
  1088. second_bigger,second_bigger,
  1089. second_bigger,second_only_rangecheck,
  1090. second_smaller,second_smaller,
  1091. second_smaller,second_smaller,
  1092. second_bool_to_int,second_int_to_bool,
  1093. second_int_real,second_real_fix,
  1094. second_fix_real,second_int_fix,second_float_float,
  1095. second_chararray_to_string,
  1096. second_proc_to_procvar,
  1097. { is constant char to pchar, is done by firstpass }
  1098. second_nothing,
  1099. second_load_smallset,
  1100. second_ansistring_to_pchar,
  1101. second_pchar_to_string,
  1102. second_nothing);
  1103. begin
  1104. { this isn't good coding, I think tc_bool_2_int, shouldn't be }
  1105. { type conversion (FK) }
  1106. { this is necessary, because second_bool_byte, have to change }
  1107. { true- and false label before calling secondpass }
  1108. if p^.convtyp<>tc_bool_2_int then
  1109. begin
  1110. secondpass(p^.left);
  1111. set_location(p^.location,p^.left^.location);
  1112. if codegenerror then
  1113. exit;
  1114. end;
  1115. if not(p^.convtyp in [tc_equal,tc_not_possible]) then
  1116. {the second argument only is for maybe_range_checking !}
  1117. secondconvert[p^.convtyp](p,p^.left,p^.convtyp)
  1118. end;
  1119. {*****************************************************************************
  1120. SecondIs
  1121. *****************************************************************************}
  1122. procedure secondis(var p : ptree);
  1123. var
  1124. pushed : tpushed;
  1125. begin
  1126. { save all used registers }
  1127. pushusedregisters(pushed,$ff);
  1128. secondpass(p^.left);
  1129. clear_location(p^.location);
  1130. p^.location.loc:=LOC_FLAGS;
  1131. p^.location.resflags:=F_NE;
  1132. { push instance to check: }
  1133. case p^.left^.location.loc of
  1134. LOC_REGISTER,LOC_CREGISTER:
  1135. begin
  1136. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,
  1137. S_L,p^.left^.location.register)));
  1138. ungetregister32(p^.left^.location.register);
  1139. end;
  1140. LOC_MEM,LOC_REFERENCE:
  1141. begin
  1142. exprasmlist^.concat(new(pai386,op_ref(A_PUSH,
  1143. S_L,newreference(p^.left^.location.reference))));
  1144. del_reference(p^.left^.location.reference);
  1145. end;
  1146. else internalerror(100);
  1147. end;
  1148. { generate type checking }
  1149. secondpass(p^.right);
  1150. case p^.right^.location.loc of
  1151. LOC_REGISTER,LOC_CREGISTER:
  1152. begin
  1153. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,
  1154. S_L,p^.right^.location.register)));
  1155. ungetregister32(p^.right^.location.register);
  1156. end;
  1157. LOC_MEM,LOC_REFERENCE:
  1158. begin
  1159. exprasmlist^.concat(new(pai386,op_ref(A_PUSH,
  1160. S_L,newreference(p^.right^.location.reference))));
  1161. del_reference(p^.right^.location.reference);
  1162. end;
  1163. else internalerror(100);
  1164. end;
  1165. emitcall('FPC_DO_IS',true);
  1166. exprasmlist^.concat(new(pai386,op_reg_reg(A_OR,S_B,R_AL,R_AL)));
  1167. popusedregisters(pushed);
  1168. end;
  1169. {*****************************************************************************
  1170. SecondAs
  1171. *****************************************************************************}
  1172. procedure secondas(var p : ptree);
  1173. var
  1174. pushed : tpushed;
  1175. begin
  1176. secondpass(p^.left);
  1177. { save all used registers }
  1178. pushusedregisters(pushed,$ff);
  1179. { push instance to check: }
  1180. case p^.left^.location.loc of
  1181. LOC_REGISTER,LOC_CREGISTER:
  1182. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,
  1183. S_L,p^.left^.location.register)));
  1184. LOC_MEM,LOC_REFERENCE:
  1185. exprasmlist^.concat(new(pai386,op_ref(A_PUSH,
  1186. S_L,newreference(p^.left^.location.reference))));
  1187. else internalerror(100);
  1188. end;
  1189. { we doesn't modifiy the left side, we check only the type }
  1190. set_location(p^.location,p^.left^.location);
  1191. { generate type checking }
  1192. secondpass(p^.right);
  1193. case p^.right^.location.loc of
  1194. LOC_REGISTER,LOC_CREGISTER:
  1195. begin
  1196. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,
  1197. S_L,p^.right^.location.register)));
  1198. ungetregister32(p^.right^.location.register);
  1199. end;
  1200. LOC_MEM,LOC_REFERENCE:
  1201. begin
  1202. exprasmlist^.concat(new(pai386,op_ref(A_PUSH,
  1203. S_L,newreference(p^.right^.location.reference))));
  1204. del_reference(p^.right^.location.reference);
  1205. end;
  1206. else internalerror(100);
  1207. end;
  1208. emitcall('FPC_DO_AS',true);
  1209. { restore register, this restores automatically the }
  1210. { result }
  1211. popusedregisters(pushed);
  1212. end;
  1213. end.
  1214. {
  1215. $Log$
  1216. Revision 1.28 1998-10-08 17:17:11 pierre
  1217. * current_module old scanner tagged as invalid if unit is recompiled
  1218. + added ppheap for better info on tracegetmem of heaptrc
  1219. (adds line column and file index)
  1220. * several memory leaks removed ith help of heaptrc !!
  1221. Revision 1.27 1998/10/06 17:16:40 pierre
  1222. * some memory leaks fixed (thanks to Peter for heaptrc !)
  1223. Revision 1.26 1998/10/02 07:20:35 florian
  1224. * range checking in units doesn't work if the units are smartlinked, fixed
  1225. Revision 1.25 1998/09/30 12:14:24 peter
  1226. * fixed boolean(longbool) conversion
  1227. Revision 1.24 1998/09/27 10:16:22 florian
  1228. * type casts pchar<->ansistring fixed
  1229. * ansistring[..] calls does now an unique call
  1230. Revision 1.23 1998/09/23 12:03:51 peter
  1231. * overloading fix for array of const
  1232. Revision 1.22 1998/09/22 15:34:09 peter
  1233. + pchar -> string conversion
  1234. Revision 1.21 1998/09/20 17:46:47 florian
  1235. * some things regarding ansistrings fixed
  1236. Revision 1.20 1998/09/17 09:42:12 peter
  1237. + pass_2 for cg386
  1238. * Message() -> CGMessage() for pass_1/pass_2
  1239. Revision 1.19 1998/09/14 10:43:46 peter
  1240. * all internal RTL functions start with FPC_
  1241. Revision 1.18 1998/09/11 12:29:40 pierre
  1242. * removed explicit range_checking as it is buggy
  1243. Revision 1.17.2.1 1998/09/11 12:08:54 pierre
  1244. * removed explicit range_check was buggy
  1245. Revision 1.17 1998/09/04 08:41:38 peter
  1246. * updated some error CGMessages
  1247. Revision 1.16 1998/09/03 17:39:03 florian
  1248. + better code for type conversation longint/dword to real type
  1249. Revision 1.15 1998/09/03 16:24:50 florian
  1250. * bug of type conversation from dword to real fixed
  1251. * bug fix of Jonas applied
  1252. Revision 1.14 1998/08/28 12:51:39 florian
  1253. + ansistring to pchar type cast fixed
  1254. Revision 1.13 1998/08/28 10:56:56 peter
  1255. * removed warnings
  1256. Revision 1.12 1998/08/14 18:18:38 peter
  1257. + dynamic set contruction
  1258. * smallsets are now working (always longint size)
  1259. Revision 1.11 1998/08/10 23:59:59 peter
  1260. * fixed dup log
  1261. Revision 1.10 1998/08/10 14:49:47 peter
  1262. + localswitches, moduleswitches, globalswitches splitting
  1263. Revision 1.9 1998/08/05 16:00:09 florian
  1264. * some fixes for ansi strings
  1265. Revision 1.8 1998/07/18 22:54:24 florian
  1266. * some ansi/wide/longstring support fixed:
  1267. o parameter passing
  1268. o returning as result from functions
  1269. Revision 1.7 1998/06/12 13:10:34 peter
  1270. * small internalerror nr change
  1271. Revision 1.6 1998/06/12 10:43:12 michael
  1272. Fixed ansistrings : is_ansistring not found
  1273. Revision 1.5 1998/06/08 13:13:30 pierre
  1274. + temporary variables now in temp_gen.pas unit
  1275. because it is processor independent
  1276. * mppc68k.bat modified to undefine i386 and support_mmx
  1277. (which are defaults for i386)
  1278. Revision 1.4 1998/06/05 17:44:10 peter
  1279. * splitted cgi386
  1280. Revision 1.3 1998/06/03 22:48:50 peter
  1281. + wordbool,longbool
  1282. * rename bis,von -> high,low
  1283. * moved some systemunit loading/creating to psystem.pas
  1284. Revision 1.2 1998/06/02 10:52:10 peter
  1285. * fixed second_bool_to_int with bool8bit return
  1286. Revision 1.1 1998/06/01 16:50:18 peter
  1287. + boolean -> ord conversion
  1288. * fixed ord -> boolean conversion
  1289. }