ncnv.pas 62 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804
  1. {
  2. $Id$
  3. Copyright (c) 2000 by Florian Klaempfl
  4. Type checking and register allocation for type converting nodes
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit ncnv;
  19. {$i defines.inc}
  20. interface
  21. uses
  22. node,
  23. symtype,types,
  24. nld;
  25. type
  26. ttypeconvnode = class(tunarynode)
  27. totype : ttype;
  28. convtype : tconverttype;
  29. constructor create(node : tnode;const t : ttype);virtual;
  30. function getcopy : tnode;override;
  31. function pass_1 : tnode;override;
  32. function det_resulttype:tnode;override;
  33. function docompare(p: tnode) : boolean; override;
  34. private
  35. function resulttype_cord_to_pointer : tnode;
  36. function resulttype_chararray_to_string : tnode;
  37. function resulttype_string_to_chararray : tnode;
  38. function resulttype_string_to_string : tnode;
  39. function resulttype_char_to_string : tnode;
  40. function resulttype_char_to_chararray : tnode;
  41. function resulttype_int_to_real : tnode;
  42. function resulttype_real_to_real : tnode;
  43. function resulttype_cchar_to_pchar : tnode;
  44. function resulttype_cstring_to_pchar : tnode;
  45. function resulttype_char_to_char : tnode;
  46. function resulttype_arrayconstructor_to_set : tnode;
  47. function resulttype_pchar_to_string : tnode;
  48. function resulttype_interface_to_guid : tnode;
  49. function resulttype_call_helper(c : tconverttype) : tnode;
  50. protected
  51. function first_int_to_int : tnode;virtual;
  52. function first_cstring_to_pchar : tnode;virtual;
  53. function first_string_to_chararray : tnode;virtual;
  54. function first_char_to_string : tnode;virtual;
  55. function first_nothing : tnode;virtual;
  56. function first_array_to_pointer : tnode;virtual;
  57. function first_int_to_real : tnode;virtual;
  58. function first_real_to_real : tnode;virtual;
  59. function first_pointer_to_array : tnode;virtual;
  60. function first_cchar_to_pchar : tnode;virtual;
  61. function first_bool_to_int : tnode;virtual;
  62. function first_int_to_bool : tnode;virtual;
  63. function first_bool_to_bool : tnode;virtual;
  64. function first_proc_to_procvar : tnode;virtual;
  65. function first_load_smallset : tnode;virtual;
  66. function first_cord_to_pointer : tnode;virtual;
  67. function first_ansistring_to_pchar : tnode;virtual;
  68. function first_arrayconstructor_to_set : tnode;virtual;
  69. function first_class_to_intf : tnode;virtual;
  70. function first_char_to_char : tnode;virtual;
  71. function first_call_helper(c : tconverttype) : tnode;
  72. procedure second_int_to_int;virtual;abstract;
  73. procedure second_string_to_string;virtual;abstract;
  74. procedure second_cstring_to_pchar;virtual;abstract;
  75. procedure second_string_to_chararray;virtual;abstract;
  76. procedure second_array_to_pointer;virtual;abstract;
  77. procedure second_pointer_to_array;virtual;abstract;
  78. procedure second_chararray_to_string;virtual;abstract;
  79. procedure second_char_to_string;virtual;abstract;
  80. procedure second_int_to_real;virtual;abstract;
  81. procedure second_real_to_real;virtual;abstract;
  82. procedure second_cord_to_pointer;virtual;abstract;
  83. procedure second_proc_to_procvar;virtual;abstract;
  84. procedure second_bool_to_int;virtual;abstract;
  85. procedure second_int_to_bool;virtual;abstract;
  86. procedure second_load_smallset;virtual;abstract;
  87. procedure second_ansistring_to_pchar;virtual;abstract;
  88. procedure second_pchar_to_string;virtual;abstract;
  89. procedure second_class_to_intf;virtual;abstract;
  90. procedure second_char_to_char;virtual;abstract;
  91. procedure second_nothing; virtual;
  92. end;
  93. ttypeconvnodeclass = class of ttypeconvnode;
  94. tasnode = class(tbinarynode)
  95. constructor create(l,r : tnode);virtual;
  96. function pass_1 : tnode;override;
  97. function det_resulttype:tnode;override;
  98. procedure pass_2;override;
  99. end;
  100. tasnodeclass = class of tasnode;
  101. tisnode = class(tbinarynode)
  102. constructor create(l,r : tnode);virtual;
  103. function pass_1 : tnode;override;
  104. function det_resulttype:tnode;override;
  105. procedure pass_2;override;
  106. end;
  107. tisnodeclass = class of tisnode;
  108. var
  109. ctypeconvnode : ttypeconvnodeclass;
  110. casnode : tasnodeclass;
  111. cisnode : tisnodeclass;
  112. procedure inserttypeconv(var p:tnode;const t:ttype);
  113. procedure arrayconstructor_to_set(var p : tarrayconstructornode);
  114. implementation
  115. uses
  116. globtype,systems,tokens,
  117. cutils,verbose,globals,widestr,
  118. symconst,symdef,symsym,symtable,
  119. ncon,ncal,nset,nadd,ninl,
  120. cgbase,
  121. htypechk,pass_1,cpubase,cpuinfo;
  122. {*****************************************************************************
  123. Helpers
  124. *****************************************************************************}
  125. procedure inserttypeconv(var p:tnode;const t:ttype);
  126. begin
  127. if not assigned(p.resulttype.def) then
  128. begin
  129. resulttypepass(p);
  130. if codegenerror then
  131. exit;
  132. end;
  133. { don't insert obsolete type conversions }
  134. if is_equal(p.resulttype.def,t.def) and
  135. not ((p.resulttype.def.deftype=setdef) and
  136. (tsetdef(p.resulttype.def).settype <>
  137. tsetdef(t.def).settype)) then
  138. begin
  139. p.resulttype:=t;
  140. end
  141. else
  142. begin
  143. p:=ctypeconvnode.create(p,t);
  144. resulttypepass(p);
  145. end;
  146. end;
  147. {*****************************************************************************
  148. Array constructor to Set Conversion
  149. *****************************************************************************}
  150. procedure arrayconstructor_to_set(var p : tarrayconstructornode);
  151. var
  152. constp : tsetconstnode;
  153. buildp,
  154. p2,p3,p4 : tnode;
  155. htype : ttype;
  156. constset : pconstset;
  157. constsetlo,
  158. constsethi : longint;
  159. procedure update_constsethi(t:ttype);
  160. begin
  161. if ((t.def.deftype=orddef) and
  162. (torddef(t.def).high>=constsethi)) then
  163. begin
  164. constsethi:=torddef(t.def).high;
  165. if htype.def=nil then
  166. begin
  167. if (constsethi>255) or
  168. (torddef(t.def).low<0) then
  169. htype:=u8bittype
  170. else
  171. htype:=t;
  172. end;
  173. if constsethi>255 then
  174. constsethi:=255;
  175. end
  176. else if ((t.def.deftype=enumdef) and
  177. (tenumdef(t.def).max>=constsethi)) then
  178. begin
  179. if htype.def=nil then
  180. htype:=t;
  181. constsethi:=tenumdef(t.def).max;
  182. end;
  183. end;
  184. procedure do_set(pos : longint);
  185. var
  186. mask,l : longint;
  187. begin
  188. if (pos>255) or (pos<0) then
  189. Message(parser_e_illegal_set_expr);
  190. if pos>constsethi then
  191. constsethi:=pos;
  192. if pos<constsetlo then
  193. constsetlo:=pos;
  194. { to do this correctly we use the 32bit array }
  195. l:=pos shr 5;
  196. mask:=1 shl (pos mod 32);
  197. { do we allow the same twice }
  198. if (pconst32bitset(constset)^[l] and mask)<>0 then
  199. Message(parser_e_illegal_set_expr);
  200. pconst32bitset(constset)^[l]:=pconst32bitset(constset)^[l] or mask;
  201. end;
  202. var
  203. l : longint;
  204. lr,hr : longint;
  205. begin
  206. new(constset);
  207. FillChar(constset^,sizeof(constset^),0);
  208. htype.reset;
  209. constsetlo:=0;
  210. constsethi:=0;
  211. constp:=csetconstnode.create(nil,htype);
  212. constp.value_set:=constset;
  213. buildp:=constp;
  214. if assigned(p.left) then
  215. begin
  216. while assigned(p) do
  217. begin
  218. p4:=nil; { will contain the tree to create the set }
  219. {split a range into p2 and p3 }
  220. if p.left.nodetype=arrayconstructorrangen then
  221. begin
  222. p2:=tarrayconstructorrangenode(p.left).left;
  223. p3:=tarrayconstructorrangenode(p.left).right;
  224. tarrayconstructorrangenode(p.left).left:=nil;
  225. tarrayconstructorrangenode(p.left).right:=nil;
  226. end
  227. else
  228. begin
  229. p2:=p.left;
  230. p.left:=nil;
  231. p3:=nil;
  232. end;
  233. resulttypepass(p2);
  234. if assigned(p3) then
  235. resulttypepass(p3);
  236. if codegenerror then
  237. break;
  238. case p2.resulttype.def.deftype of
  239. enumdef,
  240. orddef:
  241. begin
  242. getrange(p2.resulttype.def,lr,hr);
  243. if assigned(p3) then
  244. begin
  245. { this isn't good, you'll get problems with
  246. type t010 = 0..10;
  247. ts = set of t010;
  248. var s : ts;b : t010
  249. begin s:=[1,2,b]; end.
  250. if is_integer(p3^.resulttype.def) then
  251. begin
  252. inserttypeconv(p3,u8bitdef);
  253. end;
  254. }
  255. if assigned(htype.def) and not(is_equal(htype.def,p3.resulttype.def)) then
  256. begin
  257. aktfilepos:=p3.fileinfo;
  258. CGMessage(type_e_typeconflict_in_set);
  259. end
  260. else
  261. begin
  262. if (p2.nodetype=ordconstn) and (p3.nodetype=ordconstn) then
  263. begin
  264. if not(is_integer(p3.resulttype.def)) then
  265. htype:=p3.resulttype
  266. else
  267. begin
  268. inserttypeconv(p3,u8bittype);
  269. inserttypeconv(p2,u8bittype);
  270. end;
  271. for l:=tordconstnode(p2).value to tordconstnode(p3).value do
  272. do_set(l);
  273. p2.free;
  274. p3.free;
  275. end
  276. else
  277. begin
  278. update_constsethi(p2.resulttype);
  279. inserttypeconv(p2,htype);
  280. update_constsethi(p3.resulttype);
  281. inserttypeconv(p3,htype);
  282. if assigned(htype.def) then
  283. inserttypeconv(p3,htype)
  284. else
  285. inserttypeconv(p3,u8bittype);
  286. p4:=csetelementnode.create(p2,p3);
  287. end;
  288. end;
  289. end
  290. else
  291. begin
  292. { Single value }
  293. if p2.nodetype=ordconstn then
  294. begin
  295. if not(is_integer(p2.resulttype.def)) then
  296. update_constsethi(p2.resulttype)
  297. else
  298. inserttypeconv(p2,u8bittype);
  299. do_set(tordconstnode(p2).value);
  300. p2.free;
  301. end
  302. else
  303. begin
  304. update_constsethi(p2.resulttype);
  305. if assigned(htype.def) then
  306. inserttypeconv(p2,htype)
  307. else
  308. inserttypeconv(p2,u8bittype);
  309. p4:=csetelementnode.create(p2,nil);
  310. end;
  311. end;
  312. end;
  313. stringdef :
  314. begin
  315. { if we've already set elements which are constants }
  316. { throw an error }
  317. if ((htype.def=nil) and assigned(buildp)) or
  318. not(is_char(htype.def)) then
  319. CGMessage(type_e_typeconflict_in_set)
  320. else
  321. for l:=1 to length(pstring(tstringconstnode(p2).value_str)^) do
  322. do_set(ord(pstring(tstringconstnode(p2).value_str)^[l]));
  323. if htype.def=nil then
  324. htype:=cchartype;
  325. p2.free;
  326. end;
  327. else
  328. CGMessage(type_e_ordinal_expr_expected);
  329. end;
  330. { insert the set creation tree }
  331. if assigned(p4) then
  332. buildp:=caddnode.create(addn,buildp,p4);
  333. { load next and dispose current node }
  334. p2:=p;
  335. p:=tarrayconstructornode(tarrayconstructornode(p2).right);
  336. tarrayconstructornode(p2).right:=nil;
  337. p2.free;
  338. end;
  339. if (htype.def=nil) then
  340. htype:=u8bittype;
  341. end
  342. else
  343. begin
  344. { empty set [], only remove node }
  345. p.free;
  346. end;
  347. { set the initial set type }
  348. constp.resulttype.setdef(tsetdef.create(htype,constsethi));
  349. { determine the resulttype for the tree }
  350. resulttypepass(buildp);
  351. { set the new tree }
  352. p:=tarrayconstructornode(buildp);
  353. end;
  354. {*****************************************************************************
  355. TTYPECONVNODE
  356. *****************************************************************************}
  357. constructor ttypeconvnode.create(node : tnode;const t:ttype);
  358. begin
  359. inherited create(typeconvn,node);
  360. convtype:=tc_not_possible;
  361. totype:=t;
  362. if t.def=nil then
  363. internalerror(200103281);
  364. set_file_line(node);
  365. end;
  366. function ttypeconvnode.getcopy : tnode;
  367. var
  368. n : ttypeconvnode;
  369. begin
  370. n:=ttypeconvnode(inherited getcopy);
  371. n.convtype:=convtype;
  372. getcopy:=n;
  373. end;
  374. function ttypeconvnode.resulttype_cord_to_pointer : tnode;
  375. var
  376. t : tnode;
  377. begin
  378. result:=nil;
  379. if left.nodetype=ordconstn then
  380. begin
  381. { check if we have a valid pointer constant (JM) }
  382. if (sizeof(pointer) > sizeof(TConstPtrUInt)) then
  383. if (sizeof(TConstPtrUInt) = 4) then
  384. begin
  385. if (tordconstnode(left).value < low(longint)) or
  386. (tordconstnode(left).value > high(cardinal)) then
  387. CGMessage(parser_e_range_check_error);
  388. end
  389. else if (sizeof(TConstPtrUInt) = 8) then
  390. begin
  391. if (tordconstnode(left).value < low(int64)) or
  392. (tordconstnode(left).value > high(qword)) then
  393. CGMessage(parser_e_range_check_error);
  394. end
  395. else
  396. internalerror(2001020801);
  397. t:=cpointerconstnode.create(TConstPtrUInt(tordconstnode(left).value),resulttype);
  398. result:=t;
  399. end
  400. else
  401. internalerror(200104023);
  402. end;
  403. function ttypeconvnode.resulttype_chararray_to_string : tnode;
  404. begin
  405. result := ccallnode.createinternres(
  406. 'fpc_chararray_to_'+lower(tstringdef(resulttype.def).stringtypname),
  407. ccallparanode.create(left,nil),resulttype);
  408. left := nil;
  409. end;
  410. function ttypeconvnode.resulttype_string_to_chararray : tnode;
  411. var
  412. arrsize: longint;
  413. begin
  414. with tarraydef(resulttype.def) do
  415. begin
  416. if highrange<lowrange then
  417. internalerror(75432653);
  418. arrsize := highrange-lowrange+1;
  419. end;
  420. if (left.nodetype = stringconstn) and
  421. { left.length+1 since there's always a terminating #0 character (JM) }
  422. (tstringconstnode(left).len+1 >= arrsize) and
  423. (tstringdef(left.resulttype.def).string_typ=st_shortstring) then
  424. begin
  425. { handled separately }
  426. result := nil;
  427. exit;
  428. end;
  429. result := ccallnode.createinternres(
  430. 'fpc_'+lower(tstringdef(left.resulttype.def).stringtypname)+
  431. '_to_chararray',ccallparanode.create(left,ccallparanode.create(
  432. cordconstnode.create(arrsize,s32bittype),nil)),resulttype);
  433. left := nil;
  434. end;
  435. function ttypeconvnode.resulttype_string_to_string : tnode;
  436. var
  437. procname: string[31];
  438. stringpara : tcallparanode;
  439. pw : pcompilerwidestring;
  440. pc : pchar;
  441. begin
  442. result:=nil;
  443. if left.nodetype=stringconstn then
  444. begin
  445. { convert ascii 2 unicode }
  446. if (tstringdef(resulttype.def).string_typ=st_widestring) and
  447. (tstringconstnode(left).st_type in [st_ansistring,st_shortstring,st_longstring]) then
  448. begin
  449. initwidestring(pw);
  450. ascii2unicode(tstringconstnode(left).value_str,tstringconstnode(left).len,pw);
  451. ansistringdispose(tstringconstnode(left).value_str,tstringconstnode(left).len);
  452. pcompilerwidestring(tstringconstnode(left).value_str):=pw;
  453. end
  454. else
  455. { convert unicode 2 ascii }
  456. if (tstringconstnode(left).st_type=st_widestring) and
  457. (tstringdef(resulttype.def).string_typ in [st_ansistring,st_shortstring,st_longstring]) then
  458. begin
  459. pw:=pcompilerwidestring(tstringconstnode(left).value_str);
  460. getmem(pc,getlengthwidestring(pw)+1);
  461. unicode2ascii(pw,pc);
  462. donewidestring(pw);
  463. tstringconstnode(left).value_str:=pc;
  464. end;
  465. tstringconstnode(left).st_type:=tstringdef(resulttype.def).string_typ;
  466. tstringconstnode(left).resulttype:=resulttype;
  467. result:=left;
  468. left:=nil;
  469. end
  470. else
  471. begin
  472. { get the correct procedure name }
  473. procname := 'fpc_'+
  474. lower(tstringdef(left.resulttype.def).stringtypname+
  475. '_to_'+tstringdef(resulttype.def).stringtypname);
  476. { create parameter (and remove left node from typeconvnode }
  477. { since it's reused as parameter) }
  478. stringpara := ccallparanode.create(left,nil);
  479. left := nil;
  480. { hen converting to shortstrings, we have to pass high(destination) too }
  481. if (tstringdef(resulttype.def).string_typ =
  482. st_shortstring) then
  483. stringpara.right := ccallparanode.create(cinlinenode.create(
  484. in_high_x,false,self.getcopy),nil);
  485. { and create the callnode }
  486. result := ccallnode.createinternres(procname,stringpara,resulttype);
  487. end;
  488. end;
  489. function ttypeconvnode.resulttype_char_to_string : tnode;
  490. var
  491. procname: string[31];
  492. para : tcallparanode;
  493. hp : tstringconstnode;
  494. ws : pcompilerwidestring;
  495. begin
  496. result:=nil;
  497. if left.nodetype=ordconstn then
  498. begin
  499. if tstringdef(resulttype.def).string_typ=st_widestring then
  500. begin
  501. initwidestring(ws);
  502. concatwidestringchar(ws,tcompilerwidechar(chr(tordconstnode(left).value)));
  503. hp:=cstringconstnode.createwstr(ws);
  504. donewidestring(ws);
  505. end
  506. else
  507. hp:=cstringconstnode.createstr(chr(tordconstnode(left).value),tstringdef(resulttype.def).string_typ);
  508. result:=hp;
  509. end
  510. else
  511. { shortstrings are handled 'inline' }
  512. if tstringdef(resulttype.def).string_typ <> st_shortstring then
  513. begin
  514. { create the parameter }
  515. para := ccallparanode.create(left,nil);
  516. left := nil;
  517. { and the procname }
  518. procname := 'fpc_char_to_' +
  519. lower(tstringdef(resulttype.def).stringtypname);
  520. { and finally the call }
  521. result := ccallnode.createinternres(procname,para,resulttype);
  522. end;
  523. end;
  524. function ttypeconvnode.resulttype_char_to_chararray : tnode;
  525. begin
  526. if resulttype.def.size <> 1 then
  527. begin
  528. { convert first to string, then to chararray }
  529. inserttypeconv(left,cshortstringtype);
  530. inserttypeconv(left,resulttype);
  531. result:=left;
  532. left := nil;
  533. exit;
  534. end;
  535. result := nil;
  536. { a chararray with 1 element is the same as a char }
  537. set_location(location,left.location);
  538. end;
  539. function ttypeconvnode.resulttype_char_to_char : tnode;
  540. var
  541. hp : tordconstnode;
  542. begin
  543. result:=nil;
  544. if left.nodetype=ordconstn then
  545. begin
  546. if (torddef(resulttype.def).typ=uchar) and
  547. (torddef(left.resulttype.def).typ=uwidechar) then
  548. begin
  549. hp:=cordconstnode.create(
  550. ord(unicode2asciichar(tcompilerwidechar(tordconstnode(left).value))),cchartype);
  551. result:=hp;
  552. end
  553. else if (torddef(resulttype.def).typ=uwidechar) and
  554. (torddef(left.resulttype.def).typ=uchar) then
  555. begin
  556. hp:=cordconstnode.create(
  557. asciichar2unicode(chr(tordconstnode(left).value)),cwidechartype);
  558. result:=hp;
  559. end
  560. else
  561. internalerror(200105131);
  562. exit;
  563. end;
  564. end;
  565. function ttypeconvnode.resulttype_int_to_real : tnode;
  566. var
  567. t : trealconstnode;
  568. begin
  569. result:=nil;
  570. if left.nodetype=ordconstn then
  571. begin
  572. t:=crealconstnode.create(tordconstnode(left).value,resulttype);
  573. result:=t;
  574. exit;
  575. end;
  576. end;
  577. function ttypeconvnode.resulttype_real_to_real : tnode;
  578. var
  579. t : tnode;
  580. begin
  581. result:=nil;
  582. if left.nodetype=realconstn then
  583. begin
  584. t:=crealconstnode.create(trealconstnode(left).value_real,resulttype);
  585. result:=t;
  586. end;
  587. end;
  588. function ttypeconvnode.resulttype_cchar_to_pchar : tnode;
  589. begin
  590. result:=nil;
  591. if is_pwidechar(resulttype.def) then
  592. inserttypeconv(left,cwidestringtype)
  593. else
  594. inserttypeconv(left,cshortstringtype);
  595. { evaluate again, reset resulttype so the convert_typ
  596. will be calculated again and cstring_to_pchar will
  597. be used for futher conversion }
  598. result:=det_resulttype;
  599. end;
  600. function ttypeconvnode.resulttype_cstring_to_pchar : tnode;
  601. begin
  602. result:=nil;
  603. if is_pwidechar(resulttype.def) then
  604. inserttypeconv(left,cwidestringtype);
  605. end;
  606. function ttypeconvnode.resulttype_arrayconstructor_to_set : tnode;
  607. var
  608. hp : tnode;
  609. begin
  610. result:=nil;
  611. if left.nodetype<>arrayconstructorn then
  612. internalerror(5546);
  613. { remove typeconv node }
  614. hp:=left;
  615. left:=nil;
  616. { create a set constructor tree }
  617. arrayconstructor_to_set(tarrayconstructornode(hp));
  618. result:=hp;
  619. end;
  620. function ttypeconvnode.resulttype_pchar_to_string : tnode;
  621. begin
  622. result := ccallnode.createinternres(
  623. 'fpc_pchar_to_'+lower(tstringdef(resulttype.def).stringtypname),
  624. ccallparanode.create(left,nil),resulttype);
  625. left := nil;
  626. end;
  627. function ttypeconvnode.resulttype_interface_to_guid : tnode;
  628. begin
  629. if tobjectdef(left.resulttype.def).isiidguidvalid then
  630. result:=cguidconstnode.create(tobjectdef(left.resulttype.def).iidguid);
  631. end;
  632. function ttypeconvnode.resulttype_call_helper(c : tconverttype) : tnode;
  633. const
  634. resulttypeconvert : array[tconverttype] of pointer = (
  635. {equal} nil,
  636. {not_possible} nil,
  637. { string_2_string } @ttypeconvnode.resulttype_string_to_string,
  638. { char_2_string } @ttypeconvnode.resulttype_char_to_string,
  639. { char_2_chararray } @ttypeconvnode.resulttype_char_to_chararray,
  640. { pchar_2_string } @ttypeconvnode.resulttype_pchar_to_string,
  641. { cchar_2_pchar } @ttypeconvnode.resulttype_cchar_to_pchar,
  642. { cstring_2_pchar } @ttypeconvnode.resulttype_cstring_to_pchar,
  643. { ansistring_2_pchar } nil,
  644. { string_2_chararray } @ttypeconvnode.resulttype_string_to_chararray,
  645. { chararray_2_string } @ttypeconvnode.resulttype_chararray_to_string,
  646. { array_2_pointer } nil,
  647. { pointer_2_array } nil,
  648. { int_2_int } nil,
  649. { int_2_bool } nil,
  650. { bool_2_bool } nil,
  651. { bool_2_int } nil,
  652. { real_2_real } @ttypeconvnode.resulttype_real_to_real,
  653. { int_2_real } @ttypeconvnode.resulttype_int_to_real,
  654. { proc_2_procvar } nil,
  655. { arrayconstructor_2_set } @ttypeconvnode.resulttype_arrayconstructor_to_set,
  656. { load_smallset } nil,
  657. { cord_2_pointer } @ttypeconvnode.resulttype_cord_to_pointer,
  658. { intf_2_string } nil,
  659. { intf_2_guid } @ttypeconvnode.resulttype_interface_to_guid,
  660. { class_2_intf } nil,
  661. { char_2_char } @ttypeconvnode.resulttype_char_to_char,
  662. { nomal_2_smallset} nil
  663. );
  664. type
  665. tprocedureofobject = function : tnode of object;
  666. var
  667. r : packed record
  668. proc : pointer;
  669. obj : pointer;
  670. end;
  671. begin
  672. result:=nil;
  673. { this is a little bit dirty but it works }
  674. { and should be quite portable too }
  675. r.proc:=resulttypeconvert[c];
  676. r.obj:=self;
  677. if assigned(r.proc) then
  678. result:=tprocedureofobject(r){$ifdef FPC}();{$endif FPC}
  679. end;
  680. function ttypeconvnode.det_resulttype:tnode;
  681. var
  682. hp : tnode;
  683. currprocdef,
  684. aprocdef : tprocdef;
  685. begin
  686. result:=nil;
  687. resulttype:=totype;
  688. resulttypepass(left);
  689. if codegenerror then
  690. exit;
  691. { remove obsolete type conversions }
  692. if is_equal(left.resulttype.def,resulttype.def) then
  693. begin
  694. { becuase is_equal only checks the basetype for sets we need to
  695. check here if we are loading a smallset into a normalset }
  696. if (resulttype.def.deftype=setdef) and
  697. (left.resulttype.def.deftype=setdef) and
  698. ((tsetdef(resulttype.def).settype = smallset) xor
  699. (tsetdef(left.resulttype.def).settype = smallset)) then
  700. begin
  701. { try to define the set as a normalset if it's a constant set }
  702. if (tsetdef(resulttype.def).settype <> smallset) then
  703. begin
  704. if (left.nodetype=setconstn) then
  705. begin
  706. tsetdef(left.resulttype.def).changesettype(normset);
  707. result:=left;
  708. left:=nil;
  709. exit;
  710. end
  711. else
  712. convtype:=tc_load_smallset;
  713. end
  714. else
  715. convtype := tc_normal_2_smallset;
  716. exit;
  717. end
  718. else
  719. begin
  720. left.resulttype:=resulttype;
  721. result:=left;
  722. left:=nil;
  723. exit;
  724. end;
  725. end;
  726. aprocdef:=assignment_overloaded(left.resulttype.def,resulttype.def);
  727. if assigned(aprocdef) then
  728. begin
  729. procinfo^.flags:=procinfo^.flags or pi_do_call;
  730. hp:=ccallnode.create(ccallparanode.create(left,nil),
  731. overloaded_operators[_assignment],nil,nil);
  732. { tell explicitly which def we must use !! (PM) }
  733. tcallnode(hp).procdefinition:=aprocdef;
  734. left:=nil;
  735. result:=hp;
  736. exit;
  737. end;
  738. if isconvertable(left.resulttype.def,resulttype.def,convtype,left.nodetype,nf_explizit in flags)=0 then
  739. begin
  740. {Procedures have a resulttype.def of voiddef and functions of their
  741. own resulttype.def. They will therefore always be incompatible with
  742. a procvar. Because isconvertable cannot check for procedures we
  743. use an extra check for them.}
  744. if (m_tp_procvar in aktmodeswitches) then
  745. begin
  746. if (resulttype.def.deftype=procvardef) and
  747. (is_procsym_load(left) or is_procsym_call(left)) then
  748. begin
  749. if is_procsym_call(left) then
  750. begin
  751. currprocdef:=get_proc_2_procvar_def(tprocsym(tcallnode(left).symtableprocentry),tprocvardef(resulttype.def));
  752. hp:=cloadnode.create_procvar(tprocsym(tcallnode(left).symtableprocentry),
  753. currprocdef,tcallnode(left).symtableproc);
  754. if (tcallnode(left).symtableprocentry.owner.symtabletype=objectsymtable) and
  755. assigned(tcallnode(left).methodpointer) then
  756. tloadnode(hp).set_mp(tcallnode(left).methodpointer.getcopy);
  757. resulttypepass(hp);
  758. left.free;
  759. left:=hp;
  760. aprocdef:=tprocdef(left.resulttype.def);
  761. end
  762. else
  763. begin
  764. if (left.nodetype<>addrn) then
  765. aprocdef:=tprocsym(tloadnode(left).symtableentry).defs^.def;
  766. end;
  767. convtype:=tc_proc_2_procvar;
  768. { Now check if the procedure we are going to assign to
  769. the procvar, is compatible with the procvar's type }
  770. if assigned(aprocdef) then
  771. begin
  772. if not proc_to_procvar_equal(aprocdef,tprocvardef(resulttype.def),false) then
  773. CGMessage2(type_e_incompatible_types,aprocdef.typename,resulttype.def.typename);
  774. end
  775. else
  776. CGMessage2(type_e_incompatible_types,left.resulttype.def.typename,resulttype.def.typename);
  777. exit;
  778. end;
  779. end;
  780. if nf_explizit in flags then
  781. begin
  782. { check if the result could be in a register }
  783. if not(tstoreddef(resulttype.def).is_intregable) and
  784. not(tstoreddef(resulttype.def).is_fpuregable) then
  785. make_not_regable(left);
  786. { boolean to byte are special because the
  787. location can be different }
  788. if is_integer(resulttype.def) and
  789. is_boolean(left.resulttype.def) then
  790. begin
  791. convtype:=tc_bool_2_int;
  792. exit;
  793. end;
  794. { ansistring to pchar }
  795. if is_pchar(resulttype.def) and
  796. is_ansistring(left.resulttype.def) then
  797. begin
  798. convtype:=tc_ansistring_2_pchar;
  799. exit;
  800. end;
  801. { do common tc_equal cast }
  802. convtype:=tc_equal;
  803. { enum to ordinal will always be s32bit }
  804. if (left.resulttype.def.deftype=enumdef) and
  805. is_ordinal(resulttype.def) then
  806. begin
  807. if left.nodetype=ordconstn then
  808. begin
  809. hp:=cordconstnode.create(tordconstnode(left).value,resulttype);
  810. result:=hp;
  811. exit;
  812. end
  813. else
  814. begin
  815. if isconvertable(s32bittype.def,resulttype.def,convtype,ordconstn,false)=0 then
  816. CGMessage2(type_e_incompatible_types,left.resulttype.def.typename,resulttype.def.typename);
  817. end;
  818. end
  819. { ordinal to enumeration }
  820. else
  821. if (resulttype.def.deftype=enumdef) and
  822. is_ordinal(left.resulttype.def) then
  823. begin
  824. if left.nodetype=ordconstn then
  825. begin
  826. hp:=cordconstnode.create(tordconstnode(left).value,resulttype);
  827. result:=hp;
  828. exit;
  829. end
  830. else
  831. begin
  832. if IsConvertable(left.resulttype.def,s32bittype.def,convtype,ordconstn,false)=0 then
  833. CGMessage2(type_e_incompatible_types,left.resulttype.def.typename,resulttype.def.typename);
  834. end;
  835. end
  836. { nil to ordinal node }
  837. else if (left.nodetype=niln) and is_ordinal(resulttype.def) then
  838. begin
  839. hp:=cordconstnode.create(0,resulttype);
  840. result:=hp;
  841. exit;
  842. end
  843. { constant pointer to ordinal }
  844. else if is_ordinal(resulttype.def) and
  845. (left.nodetype=pointerconstn) then
  846. begin
  847. hp:=cordconstnode.create(tpointerconstnode(left).value,resulttype);
  848. result:=hp;
  849. exit;
  850. end
  851. {Are we typecasting an ordconst to a char?}
  852. else
  853. if is_char(resulttype.def) and
  854. is_ordinal(left.resulttype.def) then
  855. begin
  856. if left.nodetype=ordconstn then
  857. begin
  858. hp:=cordconstnode.create(tordconstnode(left).value,resulttype);
  859. result:=hp;
  860. exit;
  861. end
  862. else
  863. begin
  864. if IsConvertable(left.resulttype.def,u8bittype.def,convtype,ordconstn,false)=0 then
  865. CGMessage2(type_e_incompatible_types,left.resulttype.def.typename,resulttype.def.typename);
  866. end;
  867. end
  868. {Are we typecasting an ordconst to a wchar?}
  869. else
  870. if is_widechar(resulttype.def) and
  871. is_ordinal(left.resulttype.def) then
  872. begin
  873. if left.nodetype=ordconstn then
  874. begin
  875. hp:=cordconstnode.create(tordconstnode(left).value,resulttype);
  876. result:=hp;
  877. exit;
  878. end
  879. else
  880. begin
  881. if IsConvertable(left.resulttype.def,u16bittype.def,convtype,ordconstn,false)=0 then
  882. CGMessage2(type_e_incompatible_types,left.resulttype.def.typename,resulttype.def.typename);
  883. end;
  884. end
  885. { char to ordinal }
  886. else
  887. if is_char(left.resulttype.def) and
  888. is_ordinal(resulttype.def) then
  889. begin
  890. if left.nodetype=ordconstn then
  891. begin
  892. hp:=cordconstnode.create(tordconstnode(left).value,resulttype);
  893. result:=hp;
  894. exit;
  895. end
  896. else
  897. begin
  898. if IsConvertable(u8bittype.def,resulttype.def,convtype,ordconstn,false)=0 then
  899. CGMessage2(type_e_incompatible_types,left.resulttype.def.typename,resulttype.def.typename);
  900. end;
  901. end
  902. { widechar to ordinal }
  903. else
  904. if is_widechar(left.resulttype.def) and
  905. is_ordinal(resulttype.def) then
  906. begin
  907. if left.nodetype=ordconstn then
  908. begin
  909. hp:=cordconstnode.create(tordconstnode(left).value,resulttype);
  910. result:=hp;
  911. exit;
  912. end
  913. else
  914. begin
  915. if IsConvertable(u16bittype.def,resulttype.def,convtype,ordconstn,false)=0 then
  916. CGMessage2(type_e_incompatible_types,left.resulttype.def.typename,resulttype.def.typename);
  917. end;
  918. end
  919. { only if the same size or formal def }
  920. { why do we allow typecasting of voiddef ?? (PM) }
  921. else
  922. begin
  923. if not(
  924. (left.resulttype.def.deftype=formaldef) or
  925. (left.resulttype.def.size=resulttype.def.size) or
  926. (is_void(left.resulttype.def) and
  927. (left.nodetype=derefn))
  928. ) then
  929. CGMessage(cg_e_illegal_type_conversion);
  930. if ((left.resulttype.def.deftype=orddef) and
  931. (resulttype.def.deftype=pointerdef)) or
  932. ((resulttype.def.deftype=orddef) and
  933. (left.resulttype.def.deftype=pointerdef)) then
  934. CGMessage(cg_d_pointer_to_longint_conv_not_portable);
  935. end;
  936. { the conversion into a strutured type is only }
  937. { possible, if the source is not a register }
  938. if ((resulttype.def.deftype in [recorddef,stringdef,arraydef]) or
  939. ((resulttype.def.deftype=objectdef) and not(is_class(resulttype.def)))
  940. ) and (left.location.loc in [LOC_REGISTER,LOC_CREGISTER]) { and
  941. it also works if the assignment is overloaded
  942. YES but this code is not executed if assignment is overloaded (PM)
  943. not assigned(assignment_overloaded(left.resulttype.def,resulttype.def))} then
  944. CGMessage(cg_e_illegal_type_conversion);
  945. end
  946. else
  947. CGMessage2(type_e_incompatible_types,left.resulttype.def.typename,resulttype.def.typename);
  948. end;
  949. { tp7 procvar support, when right is not a procvardef and we got a
  950. loadn of a procvar then convert to a calln, the check for the
  951. result is already done in is_convertible, also no conflict with
  952. @procvar is here because that has an extra addrn }
  953. if (m_tp_procvar in aktmodeswitches) and
  954. (resulttype.def.deftype<>procvardef) and
  955. (left.resulttype.def.deftype=procvardef) and
  956. (left.nodetype=loadn) then
  957. begin
  958. hp:=ccallnode.create(nil,nil,nil,nil);
  959. tcallnode(hp).set_procvar(left);
  960. resulttypepass(hp);
  961. left:=hp;
  962. end;
  963. { remove typeconv after niln }
  964. if (left.nodetype=niln) then
  965. begin
  966. left.resulttype:=resulttype;
  967. result:=left;
  968. left:=nil;
  969. exit;
  970. end;
  971. { ordinal contants can be directly converted }
  972. if (left.nodetype=ordconstn) and is_ordinal(resulttype.def) then
  973. begin
  974. { replace the resulttype and recheck the range }
  975. left.resulttype:=resulttype;
  976. testrange(left.resulttype.def,tordconstnode(left).value,(nf_explizit in flags));
  977. result:=left;
  978. left:=nil;
  979. exit;
  980. end;
  981. { fold nil to any pointer type }
  982. if (left.nodetype=niln) and (resulttype.def.deftype=pointerdef) then
  983. begin
  984. hp:=cnilnode.create;
  985. hp.resulttype:=resulttype;
  986. result:=hp;
  987. exit;
  988. end;
  989. { further, pointerconstn to any pointer is folded too }
  990. if (left.nodetype=pointerconstn) and (resulttype.def.deftype=pointerdef) then
  991. begin
  992. left.resulttype:=resulttype;
  993. result:=left;
  994. left:=nil;
  995. exit;
  996. end;
  997. { now call the resulttype helper to do constant folding }
  998. result:=resulttype_call_helper(convtype);
  999. end;
  1000. function ttypeconvnode.first_cord_to_pointer : tnode;
  1001. begin
  1002. result:=nil;
  1003. internalerror(200104043);
  1004. end;
  1005. function ttypeconvnode.first_int_to_int : tnode;
  1006. begin
  1007. first_int_to_int:=nil;
  1008. if (left.location.loc<>LOC_REGISTER) and
  1009. (resulttype.def.size>left.resulttype.def.size) then
  1010. location.loc:=LOC_REGISTER;
  1011. if is_64bitint(resulttype.def) then
  1012. registers32:=max(registers32,2)
  1013. else
  1014. registers32:=max(registers32,1);
  1015. end;
  1016. function ttypeconvnode.first_cstring_to_pchar : tnode;
  1017. begin
  1018. first_cstring_to_pchar:=nil;
  1019. registers32:=1;
  1020. location.loc:=LOC_REGISTER;
  1021. end;
  1022. function ttypeconvnode.first_string_to_chararray : tnode;
  1023. begin
  1024. first_string_to_chararray:=nil;
  1025. registers32:=1;
  1026. location.loc:=LOC_REGISTER;
  1027. end;
  1028. function ttypeconvnode.first_char_to_string : tnode;
  1029. begin
  1030. first_char_to_string:=nil;
  1031. location.loc:=LOC_MEM;
  1032. end;
  1033. function ttypeconvnode.first_nothing : tnode;
  1034. begin
  1035. first_nothing:=nil;
  1036. location.loc:=LOC_MEM;
  1037. end;
  1038. function ttypeconvnode.first_array_to_pointer : tnode;
  1039. begin
  1040. first_array_to_pointer:=nil;
  1041. if registers32<1 then
  1042. registers32:=1;
  1043. location.loc:=LOC_REGISTER;
  1044. end;
  1045. function ttypeconvnode.first_int_to_real : tnode;
  1046. begin
  1047. first_int_to_real:=nil;
  1048. {$ifdef m68k}
  1049. if (cs_fp_emulation in aktmoduleswitches) or
  1050. (tfloatdef(resulttype.def).typ=s32real) then
  1051. begin
  1052. if registers32<1 then
  1053. registers32:=1;
  1054. end
  1055. else
  1056. if registersfpu<1 then
  1057. registersfpu:=1;
  1058. {$else not m68k}
  1059. if registersfpu<1 then
  1060. registersfpu:=1;
  1061. {$endif not m68k}
  1062. location.loc:=LOC_FPU;
  1063. end;
  1064. function ttypeconvnode.first_real_to_real : tnode;
  1065. begin
  1066. first_real_to_real:=nil;
  1067. { comp isn't a floating type }
  1068. {$ifdef i386}
  1069. if (tfloatdef(resulttype.def).typ=s64comp) and
  1070. (tfloatdef(left.resulttype.def).typ<>s64comp) and
  1071. not (nf_explizit in flags) then
  1072. CGMessage(type_w_convert_real_2_comp);
  1073. {$endif}
  1074. if registersfpu<1 then
  1075. registersfpu:=1;
  1076. location.loc:=LOC_FPU;
  1077. end;
  1078. function ttypeconvnode.first_pointer_to_array : tnode;
  1079. begin
  1080. first_pointer_to_array:=nil;
  1081. if registers32<1 then
  1082. registers32:=1;
  1083. location.loc:=LOC_REFERENCE;
  1084. end;
  1085. function ttypeconvnode.first_cchar_to_pchar : tnode;
  1086. begin
  1087. first_cchar_to_pchar:=nil;
  1088. internalerror(200104021);
  1089. end;
  1090. function ttypeconvnode.first_bool_to_int : tnode;
  1091. begin
  1092. first_bool_to_int:=nil;
  1093. { byte(boolean) or word(wordbool) or longint(longbool) must
  1094. be accepted for var parameters }
  1095. if (nf_explizit in flags) and
  1096. (left.resulttype.def.size=resulttype.def.size) and
  1097. (left.location.loc in [LOC_REFERENCE,LOC_MEM,LOC_CREGISTER]) then
  1098. exit;
  1099. { when converting to 64bit, first convert to a 32bit int and then }
  1100. { convert to a 64bit int (only necessary for 32bit processors) (JM) }
  1101. if resulttype.def.size > sizeof(aword) then
  1102. begin
  1103. result := ctypeconvnode.create(left,u32bittype);
  1104. result.toggleflag(nf_explizit);
  1105. result := ctypeconvnode.create(result,resulttype);
  1106. left := nil;
  1107. firstpass(result);
  1108. exit;
  1109. end;
  1110. location.loc:=LOC_REGISTER;
  1111. if registers32<1 then
  1112. registers32:=1;
  1113. end;
  1114. function ttypeconvnode.first_int_to_bool : tnode;
  1115. begin
  1116. first_int_to_bool:=nil;
  1117. { byte(boolean) or word(wordbool) or longint(longbool) must
  1118. be accepted for var parameters }
  1119. if (nf_explizit in flags) and
  1120. (left.resulttype.def.size=resulttype.def.size) and
  1121. (left.location.loc in [LOC_REFERENCE,LOC_MEM,LOC_CREGISTER]) then
  1122. exit;
  1123. location.loc:=LOC_REGISTER;
  1124. { need if bool to bool !!
  1125. not very nice !!
  1126. insertypeconv(left,s32bittype);
  1127. left.explizit:=true;
  1128. firstpass(left); }
  1129. if registers32<1 then
  1130. registers32:=1;
  1131. end;
  1132. function ttypeconvnode.first_bool_to_bool : tnode;
  1133. begin
  1134. first_bool_to_bool:=nil;
  1135. location.loc:=LOC_REGISTER;
  1136. if registers32<1 then
  1137. registers32:=1;
  1138. end;
  1139. function ttypeconvnode.first_char_to_char : tnode;
  1140. begin
  1141. first_char_to_char:=nil;
  1142. location.loc:=LOC_REGISTER;
  1143. if registers32<1 then
  1144. registers32:=1;
  1145. end;
  1146. function ttypeconvnode.first_proc_to_procvar : tnode;
  1147. begin
  1148. first_proc_to_procvar:=nil;
  1149. if (left.location.loc<>LOC_REFERENCE) then
  1150. CGMessage(cg_e_illegal_expression);
  1151. registers32:=left.registers32;
  1152. if registers32<1 then
  1153. registers32:=1;
  1154. location.loc:=LOC_REGISTER;
  1155. end;
  1156. function ttypeconvnode.first_load_smallset : tnode;
  1157. var
  1158. srsym: ttypesym;
  1159. p: tcallparanode;
  1160. begin
  1161. if not searchsystype('FPC_SMALL_SET',srsym) then
  1162. internalerror(200108313);
  1163. p := ccallparanode.create(left,nil);
  1164. { reused }
  1165. left := nil;
  1166. { convert parameter explicitely to fpc_small_set }
  1167. p.left := ctypeconvnode.create(p.left,srsym.restype);
  1168. p.left.toggleflag(nf_explizit);
  1169. { create call, adjust resulttype }
  1170. result :=
  1171. ccallnode.createinternres('fpc_set_load_small',p,resulttype);
  1172. firstpass(result);
  1173. end;
  1174. function ttypeconvnode.first_ansistring_to_pchar : tnode;
  1175. begin
  1176. first_ansistring_to_pchar:=nil;
  1177. location.loc:=LOC_REGISTER;
  1178. if registers32<1 then
  1179. registers32:=1;
  1180. end;
  1181. function ttypeconvnode.first_arrayconstructor_to_set : tnode;
  1182. begin
  1183. first_arrayconstructor_to_set:=nil;
  1184. internalerror(200104022);
  1185. end;
  1186. function ttypeconvnode.first_class_to_intf : tnode;
  1187. begin
  1188. first_class_to_intf:=nil;
  1189. location.loc:=LOC_REFERENCE;
  1190. if registers32<1 then
  1191. registers32:=1;
  1192. end;
  1193. function ttypeconvnode.first_call_helper(c : tconverttype) : tnode;
  1194. const
  1195. firstconvert : array[tconverttype] of pointer = (
  1196. @ttypeconvnode.first_nothing, {equal}
  1197. @ttypeconvnode.first_nothing, {not_possible}
  1198. nil, { removed in resulttype_string_to_string }
  1199. @ttypeconvnode.first_char_to_string,
  1200. @ttypeconvnode.first_nothing, { char_2_chararray, needs nothing extra }
  1201. nil, { removed in resulttype_chararray_to_string }
  1202. @ttypeconvnode.first_cchar_to_pchar,
  1203. @ttypeconvnode.first_cstring_to_pchar,
  1204. @ttypeconvnode.first_ansistring_to_pchar,
  1205. @ttypeconvnode.first_string_to_chararray,
  1206. nil, { removed in resulttype_chararray_to_string }
  1207. @ttypeconvnode.first_array_to_pointer,
  1208. @ttypeconvnode.first_pointer_to_array,
  1209. @ttypeconvnode.first_int_to_int,
  1210. @ttypeconvnode.first_int_to_bool,
  1211. @ttypeconvnode.first_bool_to_bool,
  1212. @ttypeconvnode.first_bool_to_int,
  1213. @ttypeconvnode.first_real_to_real,
  1214. @ttypeconvnode.first_int_to_real,
  1215. @ttypeconvnode.first_proc_to_procvar,
  1216. @ttypeconvnode.first_arrayconstructor_to_set,
  1217. @ttypeconvnode.first_load_smallset,
  1218. @ttypeconvnode.first_cord_to_pointer,
  1219. @ttypeconvnode.first_nothing,
  1220. @ttypeconvnode.first_nothing,
  1221. @ttypeconvnode.first_class_to_intf,
  1222. @ttypeconvnode.first_char_to_char,
  1223. @ttypeconvnode.first_nothing
  1224. );
  1225. type
  1226. tprocedureofobject = function : tnode of object;
  1227. var
  1228. r : packed record
  1229. proc : pointer;
  1230. obj : pointer;
  1231. end;
  1232. begin
  1233. { this is a little bit dirty but it works }
  1234. { and should be quite portable too }
  1235. r.proc:=firstconvert[c];
  1236. r.obj:=self;
  1237. first_call_helper:=tprocedureofobject(r){$ifdef FPC}();{$endif FPC}
  1238. end;
  1239. function ttypeconvnode.pass_1 : tnode;
  1240. begin
  1241. result:=nil;
  1242. firstpass(left);
  1243. if codegenerror then
  1244. exit;
  1245. { load the value_str from the left part }
  1246. registers32:=left.registers32;
  1247. registersfpu:=left.registersfpu;
  1248. {$ifdef SUPPORT_MMX}
  1249. registersmmx:=left.registersmmx;
  1250. {$endif}
  1251. set_location(location,left.location);
  1252. if nf_explizit in flags then
  1253. begin
  1254. { check if the result could be in a register }
  1255. if not(tstoreddef(resulttype.def).is_intregable) and
  1256. not(tstoreddef(resulttype.def).is_fpuregable) then
  1257. make_not_regable(left);
  1258. end;
  1259. if convtype=tc_equal then
  1260. begin
  1261. { remove typeconv node if left is a const. For other nodes we can't
  1262. remove it because the secondpass can still depend on the old type (PFV) }
  1263. if is_constnode(left) then
  1264. begin
  1265. left.resulttype:=resulttype;
  1266. result:=left;
  1267. left:=nil;
  1268. end;
  1269. end
  1270. else
  1271. begin
  1272. result:=first_call_helper(convtype);
  1273. end;
  1274. end;
  1275. function ttypeconvnode.docompare(p: tnode) : boolean;
  1276. begin
  1277. docompare :=
  1278. inherited docompare(p) and
  1279. (convtype = ttypeconvnode(p).convtype);
  1280. end;
  1281. procedure ttypeconvnode.second_nothing;
  1282. begin
  1283. end;
  1284. {*****************************************************************************
  1285. TISNODE
  1286. *****************************************************************************}
  1287. constructor tisnode.create(l,r : tnode);
  1288. begin
  1289. inherited create(isn,l,r);
  1290. end;
  1291. function tisnode.det_resulttype:tnode;
  1292. begin
  1293. result:=nil;
  1294. resulttypepass(left);
  1295. resulttypepass(right);
  1296. set_varstate(left,true);
  1297. set_varstate(right,true);
  1298. if codegenerror then
  1299. exit;
  1300. if (right.resulttype.def.deftype=classrefdef) then
  1301. begin
  1302. { left must be a class }
  1303. if is_class(left.resulttype.def) then
  1304. begin
  1305. { the operands must be related }
  1306. if (not(tobjectdef(left.resulttype.def).is_related(
  1307. tobjectdef(tclassrefdef(right.resulttype.def).pointertype.def)))) and
  1308. (not(tobjectdef(tclassrefdef(right.resulttype.def).pointertype.def).is_related(
  1309. tobjectdef(left.resulttype.def)))) then
  1310. CGMessage(type_e_mismatch);
  1311. end
  1312. else
  1313. CGMessage(type_e_mismatch);
  1314. end
  1315. else
  1316. CGMessage(type_e_mismatch);
  1317. resulttype:=booltype;
  1318. end;
  1319. function tisnode.pass_1 : tnode;
  1320. var
  1321. paras: tcallparanode;
  1322. begin
  1323. paras := ccallparanode.create(left,ccallparanode.create(right,nil));
  1324. left := nil;
  1325. right := nil;
  1326. result := ccallnode.createintern('fpc_do_is',paras);
  1327. firstpass(result);
  1328. end;
  1329. { dummy pass_2, it will never be called, but we need one since }
  1330. { you can't instantiate an abstract class }
  1331. procedure tisnode.pass_2;
  1332. begin
  1333. end;
  1334. {*****************************************************************************
  1335. TASNODE
  1336. *****************************************************************************}
  1337. constructor tasnode.create(l,r : tnode);
  1338. begin
  1339. inherited create(asn,l,r);
  1340. end;
  1341. function tasnode.det_resulttype:tnode;
  1342. begin
  1343. result:=nil;
  1344. resulttypepass(right);
  1345. resulttypepass(left);
  1346. set_varstate(right,true);
  1347. set_varstate(left,true);
  1348. if codegenerror then
  1349. exit;
  1350. if (right.resulttype.def.deftype=classrefdef) then
  1351. begin
  1352. { left must be a class }
  1353. if is_class(left.resulttype.def) then
  1354. begin
  1355. { the operands must be related }
  1356. if (not(tobjectdef(left.resulttype.def).is_related(
  1357. tobjectdef(tclassrefdef(right.resulttype.def).pointertype.def)))) and
  1358. (not(tobjectdef(tclassrefdef(right.resulttype.def).pointertype.def).is_related(
  1359. tobjectdef(left.resulttype.def)))) then
  1360. CGMessage(type_e_mismatch);
  1361. end
  1362. else
  1363. CGMessage(type_e_mismatch);
  1364. resulttype:=tclassrefdef(right.resulttype.def).pointertype;
  1365. end
  1366. else
  1367. CGMessage(type_e_mismatch);
  1368. end;
  1369. function tasnode.pass_1 : tnode;
  1370. var
  1371. paras: tcallparanode;
  1372. begin
  1373. paras := ccallparanode.create(left,ccallparanode.create(right,nil));
  1374. left := nil;
  1375. right := nil;
  1376. result := ccallnode.createinternres('fpc_do_as',paras,
  1377. resulttype);
  1378. firstpass(result);
  1379. end;
  1380. { dummy pass_2, it will never be called, but we need one since }
  1381. { you can't instantiate an abstract class }
  1382. procedure tasnode.pass_2;
  1383. begin
  1384. end;
  1385. begin
  1386. ctypeconvnode:=ttypeconvnode;
  1387. casnode:=tasnode;
  1388. cisnode:=tisnode;
  1389. end.
  1390. {
  1391. $Log$
  1392. Revision 1.44 2001-11-02 23:24:11 jonas
  1393. * fixed web bug 1665 (allow char to chararray type conversion) ("merged")
  1394. Revision 1.43 2001/11/02 22:58:02 peter
  1395. * procsym definition rewrite
  1396. Revision 1.42 2001/10/28 17:22:25 peter
  1397. * allow assignment of overloaded procedures to procvars when we know
  1398. which procedure to take
  1399. Revision 1.41 2001/10/20 19:28:37 peter
  1400. * interface 2 guid support
  1401. * guid constants support
  1402. Revision 1.40 2001/10/20 17:21:54 peter
  1403. * fixed size of constset when change from small to normalset
  1404. Revision 1.39 2001/09/30 16:12:46 jonas
  1405. - removed unnecessary i386 pass_2 of as- and isnode and added dummy generic ones
  1406. Revision 1.38 2001/09/29 21:32:46 jonas
  1407. * almost all second pass typeconvnode helpers are now processor independent
  1408. * fixed converting boolean to int64/qword
  1409. * fixed register allocation bugs which could cause internalerror 10
  1410. * isnode and asnode are completely processor indepent now as well
  1411. * fpc_do_as now returns its class argument (necessary to be able to use it
  1412. properly with compilerproc)
  1413. Revision 1.37 2001/09/03 13:27:42 jonas
  1414. * compilerproc implementation of set addition/substraction/...
  1415. * changed the declaration of some set helpers somewhat to accomodate the
  1416. above change
  1417. * i386 still uses the old code for comparisons of sets, because its
  1418. helpers return the results in the flags
  1419. * dummy tc_normal_2_small_set type conversion because I need the original
  1420. resulttype of the set add nodes
  1421. NOTE: you have to start a cycle with 1.0.5!
  1422. Revision 1.36 2001/09/02 21:12:06 peter
  1423. * move class of definitions into type section for delphi
  1424. Revision 1.35 2001/08/29 19:49:03 jonas
  1425. * some fixes in compilerprocs for chararray to string conversions
  1426. * conversion from string to chararray is now also done via compilerprocs
  1427. Revision 1.34 2001/08/29 12:18:07 jonas
  1428. + new createinternres() constructor for tcallnode to support setting a
  1429. custom resulttype
  1430. * compilerproc typeconversions now set the resulttype from the type
  1431. conversion for the generated call node, because the resulttype of
  1432. of the compilerproc helper isn't always exact (e.g. the ones that
  1433. return shortstrings, actually return a shortstring[x], where x is
  1434. specified by the typeconversion node)
  1435. * ti386callnode.pass_2 now always uses resulttype instead of
  1436. procsym.definition.rettype (so the custom resulttype, if any, is
  1437. always used). Note that this "rettype" stuff is only for use with
  1438. compilerprocs.
  1439. Revision 1.33 2001/08/28 13:24:46 jonas
  1440. + compilerproc implementation of most string-related type conversions
  1441. - removed all code from the compiler which has been replaced by
  1442. compilerproc implementations (using (ifdef hascompilerproc) is not
  1443. necessary in the compiler)
  1444. Revision 1.32 2001/08/26 13:36:40 florian
  1445. * some cg reorganisation
  1446. * some PPC updates
  1447. Revision 1.31 2001/08/05 13:19:51 peter
  1448. * partly fix for proc of obj=nil
  1449. Revision 1.30 2001/07/30 20:59:27 peter
  1450. * m68k updates from v10 merged
  1451. Revision 1.29 2001/07/08 21:00:15 peter
  1452. * various widestring updates, it works now mostly without charset
  1453. mapping supported
  1454. Revision 1.28 2001/05/13 15:43:46 florian
  1455. * made resultype_char_to_char a little bit robuster
  1456. Revision 1.27 2001/05/08 21:06:30 florian
  1457. * some more support for widechars commited especially
  1458. regarding type casting and constants
  1459. Revision 1.26 2001/05/04 15:52:03 florian
  1460. * some Delphi incompatibilities fixed:
  1461. - out, dispose and new can be used as idenfiers now
  1462. - const p = apointerype(nil); is supported now
  1463. + support for const p = apointertype(pointer(1234)); added
  1464. Revision 1.25 2001/04/13 22:20:58 peter
  1465. * remove wrongly placed first_call_helper
  1466. Revision 1.24 2001/04/13 01:22:08 peter
  1467. * symtable change to classes
  1468. * range check generation and errors fixed, make cycle DEBUG=1 works
  1469. * memory leaks fixed
  1470. Revision 1.23 2001/04/04 22:42:39 peter
  1471. * move constant folding into det_resulttype
  1472. Revision 1.22 2001/04/02 21:20:30 peter
  1473. * resulttype rewrite
  1474. Revision 1.21 2001/03/08 17:44:47 jonas
  1475. * fixed web bug 1430
  1476. Revision 1.20 2001/02/21 11:49:50 jonas
  1477. * evaluate typecasts of const pointers to ordinals inline ('merged')
  1478. Revision 1.19 2001/02/20 18:37:10 peter
  1479. * removed unused code
  1480. Revision 1.18 2001/02/20 13:14:18 marco
  1481. * Fix from Peter for passing a procedure of method to a other method in a method
  1482. Revision 1.17 2001/02/08 13:09:03 jonas
  1483. * fixed web bug 1396: tpointerord is now a cardinal instead of a longint,
  1484. but added a hack in ncnv so that pointer(-1) still works
  1485. Revision 1.16 2000/12/31 11:14:10 jonas
  1486. + implemented/fixed docompare() mathods for all nodes (not tested)
  1487. + nopt.pas, nadd.pas, i386/n386opt.pas: optimized nodes for adding strings
  1488. and constant strings/chars together
  1489. * n386add.pas: don't copy temp strings (of size 256) to another temp string
  1490. when adding
  1491. Revision 1.15 2000/12/08 12:41:01 jonas
  1492. * fixed bug in sign extension patch
  1493. Revision 1.14 2000/12/07 17:19:42 jonas
  1494. * new constant handling: from now on, hex constants >$7fffffff are
  1495. parsed as unsigned constants (otherwise, $80000000 got sign extended
  1496. and became $ffffffff80000000), all constants in the longint range
  1497. become longints, all constants >$7fffffff and <=cardinal($ffffffff)
  1498. are cardinals and the rest are int64's.
  1499. * added lots of longint typecast to prevent range check errors in the
  1500. compiler and rtl
  1501. * type casts of symbolic ordinal constants are now preserved
  1502. * fixed bug where the original resulttype.def wasn't restored correctly
  1503. after doing a 64bit rangecheck
  1504. Revision 1.13 2000/11/29 00:30:32 florian
  1505. * unused units removed from uses clause
  1506. * some changes for widestrings
  1507. Revision 1.12 2000/11/20 16:06:04 jonas
  1508. + allow evaluation of 64bit constant expressions at compile time
  1509. * disable range checking for explicit typecasts of constant expressions
  1510. Revision 1.11 2000/11/12 23:24:11 florian
  1511. * interfaces are basically running
  1512. Revision 1.10 2000/11/04 14:25:20 florian
  1513. + merged Attila's changes for interfaces, not tested yet
  1514. Revision 1.9 2000/10/31 22:02:48 peter
  1515. * symtable splitted, no real code changes
  1516. Revision 1.8 2000/10/14 21:52:55 peter
  1517. * fixed memory leaks
  1518. Revision 1.7 2000/10/14 10:14:50 peter
  1519. * moehrendorf oct 2000 rewrite
  1520. Revision 1.6 2000/10/01 19:48:24 peter
  1521. * lot of compile updates for cg11
  1522. Revision 1.5 2000/09/28 19:49:52 florian
  1523. *** empty log message ***
  1524. Revision 1.4 2000/09/27 18:14:31 florian
  1525. * fixed a lot of syntax errors in the n*.pas stuff
  1526. Revision 1.3 2000/09/26 20:06:13 florian
  1527. * hmm, still a lot of work to get things compilable
  1528. Revision 1.2 2000/09/26 14:59:34 florian
  1529. * more conversion work done
  1530. Revision 1.1 2000/09/25 15:37:14 florian
  1531. * more fixes
  1532. }