ncnv.pas 103 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950
  1. {
  2. Copyright (c) 2000-2002 by Florian Klaempfl
  3. Type checking and register allocation for type converting nodes
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. unit ncnv;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. node,
  22. symtype,
  23. defutil,defcmp,
  24. nld
  25. ;
  26. type
  27. ttypeconvnode = class(tunarynode)
  28. totypedef : tdef;
  29. totypedefderef : tderef;
  30. convtype : tconverttype;
  31. constructor create(node : tnode;def:tdef);virtual;
  32. constructor create_explicit(node : tnode;def:tdef);
  33. constructor create_internal(node : tnode;def:tdef);
  34. constructor create_proc_to_procvar(node : tnode);
  35. constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
  36. procedure ppuwrite(ppufile:tcompilerppufile);override;
  37. procedure buildderefimpl;override;
  38. procedure derefimpl;override;
  39. function dogetcopy : tnode;override;
  40. procedure printnodeinfo(var t : text);override;
  41. function pass_1 : tnode;override;
  42. function pass_typecheck:tnode;override;
  43. function simplify:tnode; override;
  44. procedure mark_write;override;
  45. function docompare(p: tnode) : boolean; override;
  46. function assign_allowed:boolean;
  47. procedure second_call_helper(c : tconverttype);
  48. private
  49. function typecheck_int_to_int : tnode;
  50. function typecheck_cord_to_pointer : tnode;
  51. function typecheck_chararray_to_string : tnode;
  52. function typecheck_string_to_chararray : tnode;
  53. function typecheck_string_to_string : tnode;
  54. function typecheck_char_to_string : tnode;
  55. function typecheck_char_to_chararray : tnode;
  56. function typecheck_int_to_real : tnode;
  57. function typecheck_int_to_string : tnode;
  58. function typecheck_real_to_real : tnode;
  59. function typecheck_real_to_currency : tnode;
  60. function typecheck_cchar_to_pchar : tnode;
  61. function typecheck_cstring_to_pchar : tnode;
  62. function typecheck_cstring_to_int : tnode;
  63. function typecheck_char_to_char : tnode;
  64. function typecheck_arrayconstructor_to_set : tnode;
  65. function typecheck_pchar_to_string : tnode;
  66. function typecheck_interface_to_guid : tnode;
  67. function typecheck_dynarray_to_openarray : tnode;
  68. function typecheck_pwchar_to_string : tnode;
  69. function typecheck_variant_to_dynarray : tnode;
  70. function typecheck_dynarray_to_variant : tnode;
  71. function typecheck_call_helper(c : tconverttype) : tnode;
  72. function typecheck_variant_to_enum : tnode;
  73. function typecheck_enum_to_variant : tnode;
  74. function typecheck_proc_to_procvar : tnode;
  75. function typecheck_variant_to_interface : tnode;
  76. function typecheck_interface_to_variant : tnode;
  77. function typecheck_array_2_dynarray : tnode;
  78. protected
  79. function first_int_to_int : tnode;virtual;
  80. function first_cstring_to_pchar : tnode;virtual;
  81. function first_cstring_to_int : tnode;virtual;
  82. function first_string_to_chararray : tnode;virtual;
  83. function first_char_to_string : tnode;virtual;
  84. function first_nothing : tnode;virtual;
  85. function first_array_to_pointer : tnode;virtual;
  86. function first_int_to_real : tnode;virtual;
  87. function first_real_to_real : tnode;virtual;
  88. function first_pointer_to_array : tnode;virtual;
  89. function first_cchar_to_pchar : tnode;virtual;
  90. function first_bool_to_int : tnode;virtual;
  91. function first_int_to_bool : tnode;virtual;
  92. function first_bool_to_bool : tnode;virtual;
  93. function first_proc_to_procvar : tnode;virtual;
  94. function first_load_smallset : tnode;virtual;
  95. function first_cord_to_pointer : tnode;virtual;
  96. function first_ansistring_to_pchar : tnode;virtual;
  97. function first_arrayconstructor_to_set : tnode;virtual;
  98. function first_class_to_intf : tnode;virtual;
  99. function first_char_to_char : tnode;virtual;
  100. function first_call_helper(c : tconverttype) : tnode;
  101. { these wrapper are necessary, because the first_* stuff is called }
  102. { through a table. Without the wrappers override wouldn't have }
  103. { any effect }
  104. function _first_int_to_int : tnode;
  105. function _first_cstring_to_pchar : tnode;
  106. function _first_cstring_to_int : tnode;
  107. function _first_string_to_chararray : tnode;
  108. function _first_char_to_string : tnode;
  109. function _first_nothing : tnode;
  110. function _first_array_to_pointer : tnode;
  111. function _first_int_to_real : tnode;
  112. function _first_real_to_real: tnode;
  113. function _first_pointer_to_array : tnode;
  114. function _first_cchar_to_pchar : tnode;
  115. function _first_bool_to_int : tnode;
  116. function _first_int_to_bool : tnode;
  117. function _first_bool_to_bool : tnode;
  118. function _first_proc_to_procvar : tnode;
  119. function _first_load_smallset : tnode;
  120. function _first_cord_to_pointer : tnode;
  121. function _first_ansistring_to_pchar : tnode;
  122. function _first_arrayconstructor_to_set : tnode;
  123. function _first_class_to_intf : tnode;
  124. function _first_char_to_char : tnode;
  125. procedure _second_int_to_int;virtual;
  126. procedure _second_string_to_string;virtual;
  127. procedure _second_cstring_to_pchar;virtual;
  128. procedure _second_cstring_to_int;virtual;
  129. procedure _second_string_to_chararray;virtual;
  130. procedure _second_array_to_pointer;virtual;
  131. procedure _second_pointer_to_array;virtual;
  132. procedure _second_chararray_to_string;virtual;
  133. procedure _second_char_to_string;virtual;
  134. procedure _second_int_to_real;virtual;
  135. procedure _second_real_to_real;virtual;
  136. procedure _second_cord_to_pointer;virtual;
  137. procedure _second_proc_to_procvar;virtual;
  138. procedure _second_bool_to_int;virtual;
  139. procedure _second_int_to_bool;virtual;
  140. procedure _second_bool_to_bool;virtual;
  141. procedure _second_load_smallset;virtual;
  142. procedure _second_ansistring_to_pchar;virtual;
  143. procedure _second_class_to_intf;virtual;
  144. procedure _second_char_to_char;virtual;
  145. procedure _second_nothing; virtual;
  146. procedure second_int_to_int;virtual;abstract;
  147. procedure second_string_to_string;virtual;abstract;
  148. procedure second_cstring_to_pchar;virtual;abstract;
  149. procedure second_cstring_to_int;virtual;abstract;
  150. procedure second_string_to_chararray;virtual;abstract;
  151. procedure second_array_to_pointer;virtual;abstract;
  152. procedure second_pointer_to_array;virtual;abstract;
  153. procedure second_chararray_to_string;virtual;abstract;
  154. procedure second_char_to_string;virtual;abstract;
  155. procedure second_int_to_real;virtual;abstract;
  156. procedure second_real_to_real;virtual;abstract;
  157. procedure second_cord_to_pointer;virtual;abstract;
  158. procedure second_proc_to_procvar;virtual;abstract;
  159. procedure second_bool_to_int;virtual;abstract;
  160. procedure second_int_to_bool;virtual;abstract;
  161. procedure second_bool_to_bool;virtual;abstract;
  162. procedure second_load_smallset;virtual;abstract;
  163. procedure second_ansistring_to_pchar;virtual;abstract;
  164. procedure second_class_to_intf;virtual;abstract;
  165. procedure second_char_to_char;virtual;abstract;
  166. procedure second_nothing; virtual;abstract;
  167. end;
  168. ttypeconvnodeclass = class of ttypeconvnode;
  169. tasnode = class(tbinarynode)
  170. constructor create(l,r : tnode);virtual;
  171. function pass_1 : tnode;override;
  172. function pass_typecheck:tnode;override;
  173. function dogetcopy: tnode;override;
  174. destructor destroy; override;
  175. call: tnode;
  176. end;
  177. tasnodeclass = class of tasnode;
  178. tisnode = class(tbinarynode)
  179. constructor create(l,r : tnode);virtual;
  180. function pass_1 : tnode;override;
  181. function pass_typecheck:tnode;override;
  182. procedure pass_generate_code;override;
  183. end;
  184. tisnodeclass = class of tisnode;
  185. var
  186. ctypeconvnode : ttypeconvnodeclass;
  187. casnode : tasnodeclass;
  188. cisnode : tisnodeclass;
  189. procedure inserttypeconv(var p:tnode;def:tdef);
  190. procedure inserttypeconv_internal(var p:tnode;def:tdef);
  191. procedure arrayconstructor_to_set(var p : tnode);
  192. procedure insert_varargstypeconv(var p : tnode; iscvarargs: boolean);
  193. procedure int_to_4cc(var p: tnode);
  194. implementation
  195. uses
  196. cclasses,globtype,systems,
  197. cutils,verbose,globals,widestr,
  198. symconst,symdef,symsym,symbase,symtable,
  199. ncon,ncal,nset,nadd,ninl,nmem,nmat,nbas,nutils,
  200. cgbase,procinfo,
  201. htypechk,pass_1,cpuinfo;
  202. {*****************************************************************************
  203. Helpers
  204. *****************************************************************************}
  205. procedure inserttypeconv(var p:tnode;def:tdef);
  206. begin
  207. if not assigned(p.resultdef) then
  208. begin
  209. typecheckpass(p);
  210. if codegenerror then
  211. exit;
  212. end;
  213. { don't insert obsolete type conversions }
  214. if equal_defs(p.resultdef,def) and
  215. not ((p.resultdef.deftype=setdef) and
  216. (tsetdef(p.resultdef).settype <>
  217. tsetdef(def).settype)) then
  218. begin
  219. p.resultdef:=def;
  220. end
  221. else
  222. begin
  223. p:=ctypeconvnode.create(p,def);
  224. typecheckpass(p);
  225. end;
  226. end;
  227. procedure inserttypeconv_internal(var p:tnode;def:tdef);
  228. begin
  229. if not assigned(p.resultdef) then
  230. begin
  231. typecheckpass(p);
  232. if codegenerror then
  233. exit;
  234. end;
  235. { don't insert obsolete type conversions }
  236. if equal_defs(p.resultdef,def) and
  237. not ((p.resultdef.deftype=setdef) and
  238. (tsetdef(p.resultdef).settype <>
  239. tsetdef(def).settype)) then
  240. begin
  241. p.resultdef:=def;
  242. end
  243. else
  244. begin
  245. p:=ctypeconvnode.create_internal(p,def);
  246. typecheckpass(p);
  247. end;
  248. end;
  249. {*****************************************************************************
  250. Array constructor to Set Conversion
  251. *****************************************************************************}
  252. procedure arrayconstructor_to_set(var p : tnode);
  253. var
  254. constp : tsetconstnode;
  255. buildp,
  256. p2,p3,p4 : tnode;
  257. hdef : tdef;
  258. constset : Pconstset;
  259. constsetlo,
  260. constsethi : TConstExprInt;
  261. procedure update_constsethi(def:tdef);
  262. begin
  263. if ((def.deftype=orddef) and
  264. (torddef(def).high>=constsethi)) then
  265. begin
  266. if torddef(def).typ=uwidechar then
  267. begin
  268. constsethi:=255;
  269. if hdef=nil then
  270. hdef:=def;
  271. end
  272. else
  273. begin
  274. constsethi:=torddef(def).high;
  275. if hdef=nil then
  276. begin
  277. if (constsethi>255) or
  278. (torddef(def).low<0) then
  279. hdef:=u8inttype
  280. else
  281. hdef:=def;
  282. end;
  283. if constsethi>255 then
  284. constsethi:=255;
  285. end;
  286. end
  287. else if ((def.deftype=enumdef) and
  288. (tenumdef(def).max>=constsethi)) then
  289. begin
  290. if hdef=nil then
  291. hdef:=def;
  292. constsethi:=tenumdef(def).max;
  293. end;
  294. end;
  295. procedure do_set(pos : longint);
  296. begin
  297. if (pos and not $ff)<>0 then
  298. Message(parser_e_illegal_set_expr);
  299. if pos>constsethi then
  300. constsethi:=pos;
  301. if pos<constsetlo then
  302. constsetlo:=pos;
  303. if pos in constset^ then
  304. Message(parser_e_illegal_set_expr);
  305. include(constset^,pos);
  306. end;
  307. var
  308. l : Longint;
  309. lr,hr : TConstExprInt;
  310. hp : tarrayconstructornode;
  311. begin
  312. if p.nodetype<>arrayconstructorn then
  313. internalerror(200205105);
  314. new(constset);
  315. constset^:=[];
  316. hdef:=nil;
  317. constsetlo:=0;
  318. constsethi:=0;
  319. constp:=csetconstnode.create(nil,hdef);
  320. constp.value_set:=constset;
  321. buildp:=constp;
  322. hp:=tarrayconstructornode(p);
  323. if assigned(hp.left) then
  324. begin
  325. while assigned(hp) do
  326. begin
  327. p4:=nil; { will contain the tree to create the set }
  328. {split a range into p2 and p3 }
  329. if hp.left.nodetype=arrayconstructorrangen then
  330. begin
  331. p2:=tarrayconstructorrangenode(hp.left).left;
  332. p3:=tarrayconstructorrangenode(hp.left).right;
  333. tarrayconstructorrangenode(hp.left).left:=nil;
  334. tarrayconstructorrangenode(hp.left).right:=nil;
  335. end
  336. else
  337. begin
  338. p2:=hp.left;
  339. hp.left:=nil;
  340. p3:=nil;
  341. end;
  342. typecheckpass(p2);
  343. set_varstate(p2,vs_read,[vsf_must_be_valid]);
  344. if assigned(p3) then
  345. begin
  346. typecheckpass(p3);
  347. set_varstate(p3,vs_read,[vsf_must_be_valid]);
  348. end;
  349. if codegenerror then
  350. break;
  351. case p2.resultdef.deftype of
  352. enumdef,
  353. orddef:
  354. begin
  355. getrange(p2.resultdef,lr,hr);
  356. if assigned(p3) then
  357. begin
  358. { this isn't good, you'll get problems with
  359. type t010 = 0..10;
  360. ts = set of t010;
  361. var s : ts;b : t010
  362. begin s:=[1,2,b]; end.
  363. if is_integer(p3^.resultdef) then
  364. begin
  365. inserttypeconv(p3,u8bitdef);
  366. end;
  367. }
  368. if assigned(hdef) and not(equal_defs(hdef,p3.resultdef)) then
  369. begin
  370. current_filepos:=p3.fileinfo;
  371. CGMessage(type_e_typeconflict_in_set);
  372. end
  373. else
  374. begin
  375. if (p2.nodetype=ordconstn) and (p3.nodetype=ordconstn) then
  376. begin
  377. if not(is_integer(p3.resultdef)) then
  378. hdef:=p3.resultdef
  379. else
  380. begin
  381. inserttypeconv(p3,u8inttype);
  382. inserttypeconv(p2,u8inttype);
  383. end;
  384. for l:=tordconstnode(p2).value to tordconstnode(p3).value do
  385. do_set(l);
  386. p2.free;
  387. p3.free;
  388. end
  389. else
  390. begin
  391. update_constsethi(p2.resultdef);
  392. inserttypeconv(p2,hdef);
  393. update_constsethi(p3.resultdef);
  394. inserttypeconv(p3,hdef);
  395. if assigned(hdef) then
  396. inserttypeconv(p3,hdef)
  397. else
  398. inserttypeconv(p3,u8inttype);
  399. p4:=csetelementnode.create(p2,p3);
  400. end;
  401. end;
  402. end
  403. else
  404. begin
  405. { Single value }
  406. if p2.nodetype=ordconstn then
  407. begin
  408. if not(is_integer(p2.resultdef)) then
  409. begin
  410. { for constant set elements, delphi allows the usage of elements of enumerations which
  411. have value>255 if there is no element with a value > 255 used }
  412. if (m_delphi in current_settings.modeswitches) and (p2.resultdef.deftype=enumdef) then
  413. begin
  414. if tordconstnode(p2).value>constsethi then
  415. constsethi:=tordconstnode(p2).value;
  416. if hdef=nil then
  417. hdef:=p2.resultdef;
  418. end
  419. else
  420. update_constsethi(p2.resultdef);
  421. end;
  422. if assigned(hdef) then
  423. inserttypeconv(p2,hdef)
  424. else
  425. inserttypeconv(p2,u8inttype);
  426. do_set(tordconstnode(p2).value);
  427. p2.free;
  428. end
  429. else
  430. begin
  431. update_constsethi(p2.resultdef);
  432. if assigned(hdef) then
  433. inserttypeconv(p2,hdef)
  434. else
  435. inserttypeconv(p2,u8inttype);
  436. p4:=csetelementnode.create(p2,nil);
  437. end;
  438. end;
  439. end;
  440. stringdef :
  441. begin
  442. { if we've already set elements which are constants }
  443. { throw an error }
  444. if ((hdef=nil) and assigned(buildp)) or
  445. not(is_char(hdef)) then
  446. CGMessage(type_e_typeconflict_in_set)
  447. else
  448. for l:=1 to length(pstring(tstringconstnode(p2).value_str)^) do
  449. do_set(ord(pstring(tstringconstnode(p2).value_str)^[l]));
  450. if hdef=nil then
  451. hdef:=cchartype;
  452. p2.free;
  453. end;
  454. else
  455. CGMessage(type_e_ordinal_expr_expected);
  456. end;
  457. { insert the set creation tree }
  458. if assigned(p4) then
  459. buildp:=caddnode.create(addn,buildp,p4);
  460. { load next and dispose current node }
  461. p2:=hp;
  462. hp:=tarrayconstructornode(tarrayconstructornode(p2).right);
  463. tarrayconstructornode(p2).right:=nil;
  464. p2.free;
  465. end;
  466. if (hdef=nil) then
  467. hdef:=u8inttype;
  468. end
  469. else
  470. begin
  471. { empty set [], only remove node }
  472. p.free;
  473. end;
  474. { set the initial set type }
  475. constp.resultdef:=tsetdef.create(hdef,constsethi);
  476. { determine the resultdef for the tree }
  477. typecheckpass(buildp);
  478. { set the new tree }
  479. p:=buildp;
  480. end;
  481. procedure insert_varargstypeconv(var p : tnode; iscvarargs: boolean);
  482. begin
  483. if not(iscvarargs) and
  484. (p.nodetype=stringconstn) then
  485. p:=ctypeconvnode.create_internal(p,cansistringtype)
  486. else
  487. case p.resultdef.deftype of
  488. enumdef :
  489. p:=ctypeconvnode.create_internal(p,s32inttype);
  490. arraydef :
  491. begin
  492. if is_chararray(p.resultdef) then
  493. p:=ctypeconvnode.create_internal(p,charpointertype)
  494. else
  495. if is_widechararray(p.resultdef) then
  496. p:=ctypeconvnode.create_internal(p,widecharpointertype)
  497. else
  498. CGMessagePos1(p.fileinfo,type_e_wrong_type_in_array_constructor,p.resultdef.typename);
  499. end;
  500. orddef :
  501. begin
  502. if is_integer(p.resultdef) and
  503. not(is_64bitint(p.resultdef)) then
  504. p:=ctypeconvnode.create(p,s32inttype)
  505. else if is_void(p.resultdef) then
  506. CGMessagePos1(p.fileinfo,type_e_wrong_type_in_array_constructor,p.resultdef.typename)
  507. else if iscvarargs and
  508. is_currency(p.resultdef) then
  509. p:=ctypeconvnode.create(p,s64floattype);
  510. end;
  511. floatdef :
  512. if not(iscvarargs) then
  513. begin
  514. if not(is_currency(p.resultdef)) then
  515. p:=ctypeconvnode.create(p,pbestrealtype^);
  516. end
  517. else
  518. begin
  519. if is_constrealnode(p) and
  520. not(nf_explicit in p.flags) then
  521. MessagePos(p.fileinfo,type_w_double_c_varargs);
  522. if (tfloatdef(p.resultdef).typ in [{$ifndef x86_64}s32real,{$endif}s64currency]) or
  523. (is_constrealnode(p) and
  524. not(nf_explicit in p.flags)) then
  525. p:=ctypeconvnode.create(p,s64floattype);
  526. end;
  527. procvardef :
  528. p:=ctypeconvnode.create(p,voidpointertype);
  529. stringdef:
  530. if iscvarargs then
  531. p:=ctypeconvnode.create(p,charpointertype);
  532. variantdef:
  533. if iscvarargs then
  534. CGMessagePos1(p.fileinfo,type_e_wrong_type_in_array_constructor,p.resultdef.typename);
  535. pointerdef:
  536. ;
  537. classrefdef:
  538. if iscvarargs then
  539. p:=ctypeconvnode.create(p,voidpointertype);
  540. objectdef :
  541. if iscvarargs or
  542. is_object(p.resultdef) then
  543. CGMessagePos1(p.fileinfo,type_e_wrong_type_in_array_constructor,p.resultdef.typename);
  544. else
  545. CGMessagePos1(p.fileinfo,type_e_wrong_type_in_array_constructor,p.resultdef.typename);
  546. end;
  547. typecheckpass(p);
  548. end;
  549. procedure int_to_4cc(var p: tnode);
  550. var
  551. srsym: tsym;
  552. srsymtable: tsymtable;
  553. inttemp, chararrtemp: ttempcreatenode;
  554. newblock: tblocknode;
  555. newstatement: tstatementnode;
  556. begin
  557. if (m_mac in current_settings.modeswitches) and
  558. is_integer(p.resultdef) and
  559. (p.resultdef.size = 4) then
  560. begin
  561. if not searchsym_type('FPC_INTERNAL_FOUR_CHAR_ARRAY',srsym,srsymtable) then
  562. internalerror(2006101802);
  563. if (target_info.endian = endian_big) then
  564. inserttypeconv_internal(p,ttypesym(srsym).typedef)
  565. else
  566. begin
  567. newblock := internalstatements(newstatement);
  568. inttemp := ctempcreatenode.create(p.resultdef,4,tt_persistent,true);
  569. chararrtemp := ctempcreatenode.create(ttypesym(srsym).typedef,4,tt_persistent,true);
  570. addstatement(newstatement,inttemp);
  571. addstatement(newstatement,cassignmentnode.create(
  572. ctemprefnode.create(inttemp),p));
  573. addstatement(newstatement,chararrtemp);
  574. addstatement(newstatement,cassignmentnode.create(
  575. cvecnode.create(ctemprefnode.create(chararrtemp),
  576. cordconstnode.create(1,u32inttype,false)),
  577. ctypeconvnode.create_explicit(
  578. cshlshrnode.create(shrn,ctemprefnode.create(inttemp),
  579. cordconstnode.create(24,s32inttype,false)),
  580. cchartype)));
  581. addstatement(newstatement,cassignmentnode.create(
  582. cvecnode.create(ctemprefnode.create(chararrtemp),
  583. cordconstnode.create(2,u32inttype,false)),
  584. ctypeconvnode.create_explicit(
  585. cshlshrnode.create(shrn,ctemprefnode.create(inttemp),
  586. cordconstnode.create(16,s32inttype,false)),
  587. cchartype)));
  588. addstatement(newstatement,cassignmentnode.create(
  589. cvecnode.create(ctemprefnode.create(chararrtemp),
  590. cordconstnode.create(3,u32inttype,false)),
  591. ctypeconvnode.create_explicit(
  592. cshlshrnode.create(shrn,ctemprefnode.create(inttemp),
  593. cordconstnode.create(8,s32inttype,false)),
  594. cchartype)));
  595. addstatement(newstatement,cassignmentnode.create(
  596. cvecnode.create(ctemprefnode.create(chararrtemp),
  597. cordconstnode.create(4,u32inttype,false)),
  598. ctypeconvnode.create_explicit(
  599. ctemprefnode.create(inttemp),cchartype)));
  600. addstatement(newstatement,ctempdeletenode.create(inttemp));
  601. addstatement(newstatement,ctempdeletenode.create_normal_temp(chararrtemp));
  602. addstatement(newstatement,ctemprefnode.create(chararrtemp));
  603. p := newblock;
  604. typecheckpass(p);
  605. end;
  606. end
  607. else
  608. internalerror(2006101803);
  609. end;
  610. {*****************************************************************************
  611. TTYPECONVNODE
  612. *****************************************************************************}
  613. constructor ttypeconvnode.create(node : tnode;def:tdef);
  614. begin
  615. inherited create(typeconvn,node);
  616. convtype:=tc_none;
  617. totypedef:=def;
  618. if def=nil then
  619. internalerror(200103281);
  620. fileinfo:=node.fileinfo;
  621. end;
  622. constructor ttypeconvnode.create_explicit(node : tnode;def:tdef);
  623. begin
  624. self.create(node,def);
  625. include(flags,nf_explicit);
  626. end;
  627. constructor ttypeconvnode.create_internal(node : tnode;def:tdef);
  628. begin
  629. self.create(node,def);
  630. { handle like explicit conversions }
  631. include(flags,nf_explicit);
  632. include(flags,nf_internal);
  633. end;
  634. constructor ttypeconvnode.create_proc_to_procvar(node : tnode);
  635. begin
  636. self.create(node,voidtype);
  637. convtype:=tc_proc_2_procvar;
  638. end;
  639. constructor ttypeconvnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  640. begin
  641. inherited ppuload(t,ppufile);
  642. ppufile.getderef(totypedefderef);
  643. convtype:=tconverttype(ppufile.getbyte);
  644. end;
  645. procedure ttypeconvnode.ppuwrite(ppufile:tcompilerppufile);
  646. begin
  647. inherited ppuwrite(ppufile);
  648. ppufile.putderef(totypedefderef);
  649. ppufile.putbyte(byte(convtype));
  650. end;
  651. procedure ttypeconvnode.buildderefimpl;
  652. begin
  653. inherited buildderefimpl;
  654. totypedefderef.build(totypedef);
  655. end;
  656. procedure ttypeconvnode.derefimpl;
  657. begin
  658. inherited derefimpl;
  659. totypedef:=tdef(totypedefderef.resolve);
  660. end;
  661. function ttypeconvnode.dogetcopy : tnode;
  662. var
  663. n : ttypeconvnode;
  664. begin
  665. n:=ttypeconvnode(inherited dogetcopy);
  666. n.convtype:=convtype;
  667. n.totypedef:=totypedef;
  668. dogetcopy:=n;
  669. end;
  670. procedure ttypeconvnode.printnodeinfo(var t : text);
  671. const
  672. convtyp2str : array[tconverttype] of pchar = (
  673. 'tc_none',
  674. 'tc_equal',
  675. 'tc_not_possible',
  676. 'tc_string_2_string',
  677. 'tc_char_2_string',
  678. 'tc_char_2_chararray',
  679. 'tc_pchar_2_string',
  680. 'tc_cchar_2_pchar',
  681. 'tc_cstring_2_pchar',
  682. 'tc_cstring_2_int',
  683. 'tc_ansistring_2_pchar',
  684. 'tc_string_2_chararray',
  685. 'tc_chararray_2_string',
  686. 'tc_array_2_pointer',
  687. 'tc_pointer_2_array',
  688. 'tc_int_2_int',
  689. 'tc_int_2_bool',
  690. 'tc_int_2_string',
  691. 'tc_bool_2_bool',
  692. 'tc_bool_2_int',
  693. 'tc_real_2_real',
  694. 'tc_int_2_real',
  695. 'tc_real_2_currency',
  696. 'tc_proc_2_procvar',
  697. 'tc_arrayconstructor_2_set',
  698. 'tc_load_smallset',
  699. 'tc_cord_2_pointer',
  700. 'tc_intf_2_string',
  701. 'tc_intf_2_guid',
  702. 'tc_class_2_intf',
  703. 'tc_char_2_char',
  704. 'tc_normal_2_smallset',
  705. 'tc_dynarray_2_openarray',
  706. 'tc_pwchar_2_string',
  707. 'tc_variant_2_dynarray',
  708. 'tc_dynarray_2_variant',
  709. 'tc_variant_2_enum',
  710. 'tc_enum_2_variant',
  711. 'tc_interface_2_variant',
  712. 'tc_variant_2_interface',
  713. 'tc_array_2_dynarray'
  714. );
  715. begin
  716. inherited printnodeinfo(t);
  717. write(t,', convtype = ',strpas(convtyp2str[convtype]));
  718. end;
  719. function ttypeconvnode.typecheck_cord_to_pointer : tnode;
  720. var
  721. t : tnode;
  722. begin
  723. result:=nil;
  724. if left.nodetype=ordconstn then
  725. begin
  726. { check if we have a valid pointer constant (JM) }
  727. if (sizeof(pointer) > sizeof(TConstPtrUInt)) then
  728. if (sizeof(TConstPtrUInt) = 4) then
  729. begin
  730. if (tordconstnode(left).value < low(longint)) or
  731. (tordconstnode(left).value > high(cardinal)) then
  732. CGMessage(parser_e_range_check_error);
  733. end
  734. else if (sizeof(TConstPtrUInt) = 8) then
  735. begin
  736. if (tordconstnode(left).value < low(int64)) or
  737. (tordconstnode(left).value > high(qword)) then
  738. CGMessage(parser_e_range_check_error);
  739. end
  740. else
  741. internalerror(2001020801);
  742. t:=cpointerconstnode.create(TConstPtrUInt(tordconstnode(left).value),resultdef);
  743. result:=t;
  744. end
  745. else
  746. internalerror(200104023);
  747. end;
  748. function ttypeconvnode.typecheck_chararray_to_string : tnode;
  749. var
  750. chartype : string[8];
  751. begin
  752. if is_widechar(tarraydef(left.resultdef).elementdef) then
  753. chartype:='widechar'
  754. else
  755. chartype:='char';
  756. result := ccallnode.createinternres(
  757. 'fpc_'+chartype+'array_to_'+tstringdef(resultdef).stringtypname,
  758. ccallparanode.create(cordconstnode.create(
  759. ord(tarraydef(left.resultdef).lowrange=0),booltype,false),
  760. ccallparanode.create(left,nil)),resultdef);
  761. left := nil;
  762. end;
  763. function ttypeconvnode.typecheck_string_to_chararray : tnode;
  764. var
  765. arrsize : aint;
  766. chartype : string[8];
  767. begin
  768. result := nil;
  769. with tarraydef(resultdef) do
  770. begin
  771. if highrange<lowrange then
  772. internalerror(200501051);
  773. arrsize := highrange-lowrange+1;
  774. end;
  775. if (left.nodetype = stringconstn) and
  776. (tstringconstnode(left).cst_type=cst_conststring) then
  777. begin
  778. { if the array of char is large enough we can use the string
  779. constant directly. This is handled in ncgcnv }
  780. if (arrsize>=tstringconstnode(left).len) and
  781. is_char(tarraydef(resultdef).elementdef) then
  782. exit;
  783. { Convert to wide/short/ansistring and call default helper }
  784. if is_widechar(tarraydef(resultdef).elementdef) then
  785. inserttypeconv(left,cwidestringtype)
  786. else
  787. begin
  788. if tstringconstnode(left).len>255 then
  789. inserttypeconv(left,cansistringtype)
  790. else
  791. inserttypeconv(left,cshortstringtype);
  792. end;
  793. end;
  794. if is_widechar(tarraydef(resultdef).elementdef) then
  795. chartype:='widechar'
  796. else
  797. chartype:='char';
  798. result := ccallnode.createinternres(
  799. 'fpc_'+tstringdef(left.resultdef).stringtypname+
  800. '_to_'+chartype+'array',ccallparanode.create(left,ccallparanode.create(
  801. cordconstnode.create(arrsize,s32inttype,true),nil)),resultdef);
  802. left := nil;
  803. end;
  804. function ttypeconvnode.typecheck_string_to_string : tnode;
  805. var
  806. procname: string[31];
  807. stringpara : tcallparanode;
  808. begin
  809. result:=nil;
  810. if left.nodetype=stringconstn then
  811. begin
  812. tstringconstnode(left).changestringtype(resultdef);
  813. result:=left;
  814. left:=nil;
  815. end
  816. else
  817. begin
  818. { get the correct procedure name }
  819. procname := 'fpc_'+tstringdef(left.resultdef).stringtypname+
  820. '_to_'+tstringdef(resultdef).stringtypname;
  821. { create parameter (and remove left node from typeconvnode }
  822. { since it's reused as parameter) }
  823. stringpara := ccallparanode.create(left,nil);
  824. left := nil;
  825. { when converting to shortstrings, we have to pass high(destination) too }
  826. if (tstringdef(resultdef).string_typ = st_shortstring) then
  827. stringpara.right := ccallparanode.create(cinlinenode.create(
  828. in_high_x,false,self.getcopy),nil);
  829. { and create the callnode }
  830. result := ccallnode.createinternres(procname,stringpara,resultdef);
  831. end;
  832. end;
  833. function ttypeconvnode.typecheck_char_to_string : tnode;
  834. var
  835. procname: string[31];
  836. para : tcallparanode;
  837. hp : tstringconstnode;
  838. ws : pcompilerwidestring;
  839. begin
  840. result:=nil;
  841. if left.nodetype=ordconstn then
  842. begin
  843. if tstringdef(resultdef).string_typ=st_widestring then
  844. begin
  845. initwidestring(ws);
  846. if torddef(left.resultdef).typ=uwidechar then
  847. concatwidestringchar(ws,tcompilerwidechar(tordconstnode(left).value))
  848. else
  849. concatwidestringchar(ws,tcompilerwidechar(chr(tordconstnode(left).value)));
  850. hp:=cstringconstnode.createwstr(ws);
  851. donewidestring(ws);
  852. end
  853. else
  854. begin
  855. hp:=cstringconstnode.createstr(chr(tordconstnode(left).value));
  856. tstringconstnode(hp).changestringtype(resultdef);
  857. end;
  858. result:=hp;
  859. end
  860. else
  861. { shortstrings are handled 'inline' }
  862. if tstringdef(resultdef).string_typ <> st_shortstring then
  863. begin
  864. { create the parameter }
  865. para := ccallparanode.create(left,nil);
  866. left := nil;
  867. { and the procname }
  868. procname := 'fpc_char_to_' +tstringdef(resultdef).stringtypname;
  869. { and finally the call }
  870. result := ccallnode.createinternres(procname,para,resultdef);
  871. end
  872. else
  873. begin
  874. { create word(byte(char) shl 8 or 1) for litte endian machines }
  875. { and word(byte(char) or 256) for big endian machines }
  876. left := ctypeconvnode.create_internal(left,u8inttype);
  877. if (target_info.endian = endian_little) then
  878. left := caddnode.create(orn,
  879. cshlshrnode.create(shln,left,cordconstnode.create(8,s32inttype,false)),
  880. cordconstnode.create(1,s32inttype,false))
  881. else
  882. left := caddnode.create(orn,left,
  883. cordconstnode.create(1 shl 8,s32inttype,false));
  884. left := ctypeconvnode.create_internal(left,u16inttype);
  885. typecheckpass(left);
  886. end;
  887. end;
  888. function ttypeconvnode.typecheck_char_to_chararray : tnode;
  889. begin
  890. if resultdef.size <> 1 then
  891. begin
  892. { convert first to string, then to chararray }
  893. inserttypeconv(left,cshortstringtype);
  894. inserttypeconv(left,resultdef);
  895. result:=left;
  896. left := nil;
  897. exit;
  898. end;
  899. result := nil;
  900. end;
  901. function ttypeconvnode.typecheck_char_to_char : tnode;
  902. var
  903. hp : tordconstnode;
  904. begin
  905. result:=nil;
  906. if left.nodetype=ordconstn then
  907. begin
  908. if (torddef(resultdef).typ=uchar) and
  909. (torddef(left.resultdef).typ=uwidechar) then
  910. begin
  911. hp:=cordconstnode.create(
  912. ord(unicode2asciichar(tcompilerwidechar(tordconstnode(left).value))),
  913. cchartype,true);
  914. result:=hp;
  915. end
  916. else if (torddef(resultdef).typ=uwidechar) and
  917. (torddef(left.resultdef).typ=uchar) then
  918. begin
  919. hp:=cordconstnode.create(
  920. asciichar2unicode(chr(tordconstnode(left).value)),
  921. cwidechartype,true);
  922. result:=hp;
  923. end
  924. else
  925. internalerror(200105131);
  926. exit;
  927. end;
  928. end;
  929. function ttypeconvnode.typecheck_int_to_int : tnode;
  930. var
  931. v : TConstExprInt;
  932. begin
  933. result:=nil;
  934. if left.nodetype=ordconstn then
  935. begin
  936. v:=tordconstnode(left).value;
  937. if is_currency(resultdef) then
  938. v:=v*10000;
  939. if (resultdef.deftype=pointerdef) then
  940. result:=cpointerconstnode.create(TConstPtrUInt(v),resultdef)
  941. else
  942. begin
  943. if is_currency(left.resultdef) then
  944. v:=v div 10000;
  945. result:=cordconstnode.create(v,resultdef,false);
  946. end;
  947. end
  948. else if left.nodetype=pointerconstn then
  949. begin
  950. v:=tpointerconstnode(left).value;
  951. if (resultdef.deftype=pointerdef) then
  952. result:=cpointerconstnode.create(v,resultdef)
  953. else
  954. begin
  955. if is_currency(resultdef) then
  956. v:=v*10000;
  957. result:=cordconstnode.create(v,resultdef,false);
  958. end;
  959. end
  960. else
  961. begin
  962. { multiply by 10000 for currency. We need to use getcopy to pass
  963. the argument because the current node is always disposed. Only
  964. inserting the multiply in the left node is not possible because
  965. it'll get in an infinite loop to convert int->currency }
  966. if is_currency(resultdef) then
  967. begin
  968. result:=caddnode.create(muln,getcopy,cordconstnode.create(10000,resultdef,false));
  969. include(result.flags,nf_is_currency);
  970. end
  971. else if is_currency(left.resultdef) then
  972. begin
  973. result:=cmoddivnode.create(divn,getcopy,cordconstnode.create(10000,resultdef,false));
  974. include(result.flags,nf_is_currency);
  975. end;
  976. end;
  977. end;
  978. function ttypeconvnode.typecheck_int_to_real : tnode;
  979. var
  980. rv : bestreal;
  981. begin
  982. result:=nil;
  983. if left.nodetype=ordconstn then
  984. begin
  985. rv:=tordconstnode(left).value;
  986. if is_currency(resultdef) then
  987. rv:=rv*10000.0
  988. else if is_currency(left.resultdef) then
  989. rv:=rv/10000.0;
  990. result:=crealconstnode.create(rv,resultdef);
  991. end
  992. else
  993. begin
  994. { multiply by 10000 for currency. We need to use getcopy to pass
  995. the argument because the current node is always disposed. Only
  996. inserting the multiply in the left node is not possible because
  997. it'll get in an infinite loop to convert int->currency }
  998. if is_currency(resultdef) then
  999. begin
  1000. result:=caddnode.create(muln,getcopy,crealconstnode.create(10000.0,resultdef));
  1001. include(result.flags,nf_is_currency);
  1002. end
  1003. else if is_currency(left.resultdef) then
  1004. begin
  1005. result:=caddnode.create(slashn,getcopy,crealconstnode.create(10000.0,resultdef));
  1006. include(result.flags,nf_is_currency);
  1007. end;
  1008. end;
  1009. end;
  1010. function ttypeconvnode.typecheck_real_to_currency : tnode;
  1011. begin
  1012. if not is_currency(resultdef) then
  1013. internalerror(200304221);
  1014. result:=nil;
  1015. left:=caddnode.create(muln,left,crealconstnode.create(10000.0,left.resultdef));
  1016. include(left.flags,nf_is_currency);
  1017. typecheckpass(left);
  1018. { Convert constants directly, else call Round() }
  1019. if left.nodetype=realconstn then
  1020. result:=cordconstnode.create(round(trealconstnode(left).value_real),resultdef,false)
  1021. else
  1022. result:=ccallnode.createinternres('fpc_round_real',
  1023. ccallparanode.create(left,nil),resultdef);
  1024. left:=nil;
  1025. end;
  1026. function ttypeconvnode.typecheck_int_to_string : tnode;
  1027. begin
  1028. if (m_mac in current_settings.modeswitches) and
  1029. is_integer(left.resultdef) and
  1030. (left.resultdef.size = 4) then
  1031. begin
  1032. int_to_4cc(left);
  1033. inserttypeconv(left,resultdef);
  1034. result := left;
  1035. left := nil;
  1036. end
  1037. else
  1038. internalerror(2006101803);
  1039. end;
  1040. function ttypeconvnode.typecheck_real_to_real : tnode;
  1041. begin
  1042. result:=nil;
  1043. if is_currency(left.resultdef) and not(is_currency(resultdef)) then
  1044. begin
  1045. left:=caddnode.create(slashn,left,crealconstnode.create(10000.0,left.resultdef));
  1046. include(left.flags,nf_is_currency);
  1047. typecheckpass(left);
  1048. end
  1049. else
  1050. if is_currency(resultdef) and not(is_currency(left.resultdef)) then
  1051. begin
  1052. left:=caddnode.create(muln,left,crealconstnode.create(10000.0,left.resultdef));
  1053. include(left.flags,nf_is_currency);
  1054. typecheckpass(left);
  1055. end;
  1056. end;
  1057. function ttypeconvnode.typecheck_cchar_to_pchar : tnode;
  1058. begin
  1059. result:=nil;
  1060. if is_pwidechar(resultdef) then
  1061. inserttypeconv(left,cwidestringtype)
  1062. else
  1063. inserttypeconv(left,cshortstringtype);
  1064. { evaluate again, reset resultdef so the convert_typ
  1065. will be calculated again and cstring_to_pchar will
  1066. be used for futher conversion }
  1067. convtype:=tc_none;
  1068. result:=pass_typecheck;
  1069. end;
  1070. function ttypeconvnode.typecheck_cstring_to_pchar : tnode;
  1071. begin
  1072. result:=nil;
  1073. if is_pwidechar(resultdef) then
  1074. inserttypeconv(left,cwidestringtype)
  1075. else
  1076. if is_pchar(resultdef) and
  1077. is_widestring(left.resultdef) then
  1078. inserttypeconv(left,cansistringtype);
  1079. end;
  1080. function ttypeconvnode.typecheck_cstring_to_int : tnode;
  1081. var
  1082. fcc : cardinal;
  1083. pb : pbyte;
  1084. begin
  1085. result:=nil;
  1086. if left.nodetype<>stringconstn then
  1087. internalerror(200510012);
  1088. if tstringconstnode(left).len=4 then
  1089. begin
  1090. pb:=pbyte(tstringconstnode(left).value_str);
  1091. fcc:=(pb[0] shl 24) or (pb[1] shl 16) or (pb[2] shl 8) or pb[3];
  1092. result:=cordconstnode.create(fcc,u32inttype,false);
  1093. end
  1094. else
  1095. CGMessage2(type_e_illegal_type_conversion,left.resultdef.GetTypeName,resultdef.GetTypeName);
  1096. end;
  1097. function ttypeconvnode.typecheck_arrayconstructor_to_set : tnode;
  1098. var
  1099. hp : tnode;
  1100. begin
  1101. result:=nil;
  1102. if left.nodetype<>arrayconstructorn then
  1103. internalerror(5546);
  1104. { remove typeconv node }
  1105. hp:=left;
  1106. left:=nil;
  1107. { create a set constructor tree }
  1108. arrayconstructor_to_set(hp);
  1109. result:=hp;
  1110. end;
  1111. function ttypeconvnode.typecheck_pchar_to_string : tnode;
  1112. begin
  1113. result := ccallnode.createinternres(
  1114. 'fpc_pchar_to_'+tstringdef(resultdef).stringtypname,
  1115. ccallparanode.create(left,nil),resultdef);
  1116. left := nil;
  1117. end;
  1118. function ttypeconvnode.typecheck_interface_to_guid : tnode;
  1119. begin
  1120. if assigned(tobjectdef(left.resultdef).iidguid) then
  1121. result:=cguidconstnode.create(tobjectdef(left.resultdef).iidguid^);
  1122. end;
  1123. function ttypeconvnode.typecheck_dynarray_to_openarray : tnode;
  1124. begin
  1125. { a dynamic array is a pointer to an array, so to convert it to }
  1126. { an open array, we have to dereference it (JM) }
  1127. result := ctypeconvnode.create_internal(left,voidpointertype);
  1128. typecheckpass(result);
  1129. { left is reused }
  1130. left := nil;
  1131. result := cderefnode.create(result);
  1132. include(result.flags,nf_no_checkpointer);
  1133. result.resultdef := resultdef;
  1134. end;
  1135. function ttypeconvnode.typecheck_pwchar_to_string : tnode;
  1136. begin
  1137. result := ccallnode.createinternres(
  1138. 'fpc_pwidechar_to_'+tstringdef(resultdef).stringtypname,
  1139. ccallparanode.create(left,nil),resultdef);
  1140. left := nil;
  1141. end;
  1142. function ttypeconvnode.typecheck_variant_to_dynarray : tnode;
  1143. begin
  1144. result := ccallnode.createinternres(
  1145. 'fpc_variant_to_dynarray',
  1146. ccallparanode.create(caddrnode.create_internal(crttinode.create(tstoreddef(resultdef),initrtti)),
  1147. ccallparanode.create(left,nil)
  1148. ),resultdef);
  1149. typecheckpass(result);
  1150. left:=nil;
  1151. end;
  1152. function ttypeconvnode.typecheck_dynarray_to_variant : tnode;
  1153. begin
  1154. result := ccallnode.createinternres(
  1155. 'fpc_dynarray_to_variant',
  1156. ccallparanode.create(caddrnode.create_internal(crttinode.create(tstoreddef(left.resultdef),initrtti)),
  1157. ccallparanode.create(ctypeconvnode.create_explicit(left,voidpointertype),nil)
  1158. ),resultdef);
  1159. typecheckpass(result);
  1160. left:=nil;
  1161. end;
  1162. function ttypeconvnode.typecheck_variant_to_interface : tnode;
  1163. begin
  1164. result := ccallnode.createinternres(
  1165. 'fpc_variant_to_interface',
  1166. ccallparanode.create(left,nil)
  1167. ,resultdef);
  1168. typecheckpass(result);
  1169. left:=nil;
  1170. end;
  1171. function ttypeconvnode.typecheck_interface_to_variant : tnode;
  1172. begin
  1173. result := ccallnode.createinternres(
  1174. 'fpc_interface_to_variant',
  1175. ccallparanode.create(left,nil)
  1176. ,resultdef);
  1177. typecheckpass(result);
  1178. left:=nil;
  1179. end;
  1180. function ttypeconvnode.typecheck_variant_to_enum : tnode;
  1181. begin
  1182. result := ctypeconvnode.create_internal(left,sinttype);
  1183. result := ctypeconvnode.create_internal(result,resultdef);
  1184. typecheckpass(result);
  1185. { left is reused }
  1186. left := nil;
  1187. end;
  1188. function ttypeconvnode.typecheck_enum_to_variant : tnode;
  1189. begin
  1190. result := ctypeconvnode.create_internal(left,sinttype);
  1191. result := ctypeconvnode.create_internal(result,cvarianttype);
  1192. typecheckpass(result);
  1193. { left is reused }
  1194. left := nil;
  1195. end;
  1196. function ttypeconvnode.typecheck_array_2_dynarray : tnode;
  1197. var
  1198. newstatement : tstatementnode;
  1199. temp : ttempcreatenode;
  1200. temp2 : ttempcreatenode;
  1201. begin
  1202. { create statements with call to getmem+initialize }
  1203. result:=internalstatements(newstatement);
  1204. { create temp for result }
  1205. temp:=ctempcreatenode.create(resultdef,resultdef.size,tt_persistent,true);
  1206. addstatement(newstatement,temp);
  1207. { get temp for array of lengths }
  1208. temp2:=ctempcreatenode.create(sinttype,sinttype.size,tt_persistent,false);
  1209. addstatement(newstatement,temp2);
  1210. { one dimensional }
  1211. addstatement(newstatement,cassignmentnode.create(
  1212. ctemprefnode.create_offset(temp2,0),
  1213. cordconstnode.create
  1214. (tarraydef(left.resultdef).highrange+1,s32inttype,true)));
  1215. { create call to fpc_dynarr_setlength }
  1216. addstatement(newstatement,ccallnode.createintern('fpc_dynarray_setlength',
  1217. ccallparanode.create(caddrnode.create_internal
  1218. (ctemprefnode.create(temp2)),
  1219. ccallparanode.create(cordconstnode.create
  1220. (1,s32inttype,true),
  1221. ccallparanode.create(caddrnode.create_internal
  1222. (crttinode.create(tstoreddef(resultdef),initrtti)),
  1223. ccallparanode.create(
  1224. ctypeconvnode.create_internal(
  1225. ctemprefnode.create(temp),voidpointertype),
  1226. nil))))
  1227. ));
  1228. addstatement(newstatement,ctempdeletenode.create(temp2));
  1229. { copy ... }
  1230. addstatement(newstatement,cassignmentnode.create(
  1231. ctypeconvnode.create_internal(cderefnode.create(ctypeconvnode.create_internal(ctemprefnode.create(temp),voidpointertype)),left.resultdef),
  1232. left
  1233. ));
  1234. { left is reused }
  1235. left:=nil;
  1236. { the last statement should return the value as
  1237. location and type, this is done be referencing the
  1238. temp and converting it first from a persistent temp to
  1239. normal temp }
  1240. addstatement(newstatement,ctempdeletenode.create_normal_temp(temp));
  1241. addstatement(newstatement,ctemprefnode.create(temp));
  1242. end;
  1243. procedure copyparasym(p:TNamedIndexItem;arg:pointer);
  1244. var
  1245. newparast : tsymtable absolute arg;
  1246. vs : tparavarsym;
  1247. begin
  1248. if tsym(p).typ<>paravarsym then
  1249. exit;
  1250. with tparavarsym(p) do
  1251. begin
  1252. vs:=tparavarsym.create(realname,paranr,varspez,vardef,varoptions);
  1253. vs.defaultconstsym:=defaultconstsym;
  1254. newparast.insert(vs);
  1255. end;
  1256. end;
  1257. function ttypeconvnode.typecheck_proc_to_procvar : tnode;
  1258. var
  1259. pd : tabstractprocdef;
  1260. begin
  1261. result:=nil;
  1262. pd:=tabstractprocdef(left.resultdef);
  1263. { create procvardef }
  1264. resultdef:=tprocvardef.create(pd.parast.symtablelevel);
  1265. tprocvardef(resultdef).proctypeoption:=pd.proctypeoption;
  1266. tprocvardef(resultdef).proccalloption:=pd.proccalloption;
  1267. tprocvardef(resultdef).procoptions:=pd.procoptions;
  1268. tprocvardef(resultdef).returndef:=pd.returndef;
  1269. { method ? then set the methodpointer flag }
  1270. if (pd.owner.symtabletype=objectsymtable) then
  1271. include(tprocvardef(resultdef).procoptions,po_methodpointer);
  1272. { was it a local procedure? }
  1273. if (pd.owner.symtabletype=localsymtable) then
  1274. include(tprocvardef(resultdef).procoptions,po_local);
  1275. { only need the address of the method? this is needed
  1276. for @tobject.create. In this case there will be a loadn without
  1277. a methodpointer. }
  1278. if (left.nodetype=loadn) and
  1279. not assigned(tloadnode(left).left) then
  1280. include(tprocvardef(resultdef).procoptions,po_addressonly);
  1281. { Add parameters use only references, we don't need to keep the
  1282. parast. We use the parast from the original function to calculate
  1283. our parameter data and reset it afterwards }
  1284. pd.parast.foreach_static(@copyparasym,tprocvardef(resultdef).parast);
  1285. tprocvardef(resultdef).calcparas;
  1286. end;
  1287. function ttypeconvnode.typecheck_call_helper(c : tconverttype) : tnode;
  1288. const
  1289. resultdefconvert : array[tconverttype] of pointer = (
  1290. {none} nil,
  1291. {equal} nil,
  1292. {not_possible} nil,
  1293. { string_2_string } @ttypeconvnode.typecheck_string_to_string,
  1294. { char_2_string } @ttypeconvnode.typecheck_char_to_string,
  1295. { char_2_chararray } @ttypeconvnode.typecheck_char_to_chararray,
  1296. { pchar_2_string } @ttypeconvnode.typecheck_pchar_to_string,
  1297. { cchar_2_pchar } @ttypeconvnode.typecheck_cchar_to_pchar,
  1298. { cstring_2_pchar } @ttypeconvnode.typecheck_cstring_to_pchar,
  1299. { cstring_2_int } @ttypeconvnode.typecheck_cstring_to_int,
  1300. { ansistring_2_pchar } nil,
  1301. { string_2_chararray } @ttypeconvnode.typecheck_string_to_chararray,
  1302. { chararray_2_string } @ttypeconvnode.typecheck_chararray_to_string,
  1303. { array_2_pointer } nil,
  1304. { pointer_2_array } nil,
  1305. { int_2_int } @ttypeconvnode.typecheck_int_to_int,
  1306. { int_2_bool } nil,
  1307. { int_2_string } @ttypeconvnode.typecheck_int_to_string,
  1308. { bool_2_bool } nil,
  1309. { bool_2_int } nil,
  1310. { real_2_real } @ttypeconvnode.typecheck_real_to_real,
  1311. { int_2_real } @ttypeconvnode.typecheck_int_to_real,
  1312. { real_2_currency } @ttypeconvnode.typecheck_real_to_currency,
  1313. { proc_2_procvar } @ttypeconvnode.typecheck_proc_to_procvar,
  1314. { arrayconstructor_2_set } @ttypeconvnode.typecheck_arrayconstructor_to_set,
  1315. { load_smallset } nil,
  1316. { cord_2_pointer } @ttypeconvnode.typecheck_cord_to_pointer,
  1317. { intf_2_string } nil,
  1318. { intf_2_guid } @ttypeconvnode.typecheck_interface_to_guid,
  1319. { class_2_intf } nil,
  1320. { char_2_char } @ttypeconvnode.typecheck_char_to_char,
  1321. { normal_2_smallset} nil,
  1322. { dynarray_2_openarray} @ttypeconvnode.typecheck_dynarray_to_openarray,
  1323. { pwchar_2_string} @ttypeconvnode.typecheck_pwchar_to_string,
  1324. { variant_2_dynarray} @ttypeconvnode.typecheck_variant_to_dynarray,
  1325. { dynarray_2_variant} @ttypeconvnode.typecheck_dynarray_to_variant,
  1326. { variant_2_enum} @ttypeconvnode.typecheck_variant_to_enum,
  1327. { enum_2_variant} @ttypeconvnode.typecheck_enum_to_variant,
  1328. { variant_2_interface} @ttypeconvnode.typecheck_interface_to_variant,
  1329. { interface_2_variant} @ttypeconvnode.typecheck_variant_to_interface,
  1330. { array_2_dynarray} @ttypeconvnode.typecheck_array_2_dynarray
  1331. );
  1332. type
  1333. tprocedureofobject = function : tnode of object;
  1334. var
  1335. r : packed record
  1336. proc : pointer;
  1337. obj : pointer;
  1338. end;
  1339. begin
  1340. result:=nil;
  1341. { this is a little bit dirty but it works }
  1342. { and should be quite portable too }
  1343. r.proc:=resultdefconvert[c];
  1344. r.obj:=self;
  1345. if assigned(r.proc) then
  1346. result:=tprocedureofobject(r)();
  1347. end;
  1348. function ttypeconvnode.pass_typecheck:tnode;
  1349. var
  1350. hdef : tdef;
  1351. hp : tnode;
  1352. currprocdef : tabstractprocdef;
  1353. aprocdef : tprocdef;
  1354. eq : tequaltype;
  1355. cdoptions : tcompare_defs_options;
  1356. begin
  1357. result:=nil;
  1358. resultdef:=totypedef;
  1359. typecheckpass(left);
  1360. if codegenerror then
  1361. exit;
  1362. { When absolute force tc_equal }
  1363. if (nf_absolute in flags) then
  1364. begin
  1365. convtype:=tc_equal;
  1366. if not(tstoreddef(resultdef).is_intregable) and
  1367. not(tstoreddef(resultdef).is_fpuregable) then
  1368. make_not_regable(left,vr_addr);
  1369. exit;
  1370. end;
  1371. { tp procvar support. Skip typecasts to procvar, record or set. Those
  1372. convert on the procvar value. This is used to access the
  1373. fields of a methodpointer }
  1374. if not(nf_load_procvar in flags) and
  1375. not(resultdef.deftype in [procvardef,recorddef,setdef]) then
  1376. maybe_call_procvar(left,true);
  1377. { convert array constructors to sets, because there is no conversion
  1378. possible for array constructors }
  1379. if (resultdef.deftype<>arraydef) and
  1380. is_array_constructor(left.resultdef) then
  1381. begin
  1382. arrayconstructor_to_set(left);
  1383. typecheckpass(left);
  1384. end;
  1385. if convtype=tc_none then
  1386. begin
  1387. cdoptions:=[cdo_check_operator,cdo_allow_variant];
  1388. if nf_explicit in flags then
  1389. include(cdoptions,cdo_explicit);
  1390. if nf_internal in flags then
  1391. include(cdoptions,cdo_internal);
  1392. eq:=compare_defs_ext(left.resultdef,resultdef,left.nodetype,convtype,aprocdef,cdoptions);
  1393. case eq of
  1394. te_exact,
  1395. te_equal :
  1396. begin
  1397. result := simplify;
  1398. if assigned(result) then
  1399. exit;
  1400. { because is_equal only checks the basetype for sets we need to
  1401. check here if we are loading a smallset into a normalset }
  1402. if (resultdef.deftype=setdef) and
  1403. (left.resultdef.deftype=setdef) and
  1404. ((tsetdef(resultdef).settype = smallset) xor
  1405. (tsetdef(left.resultdef).settype = smallset)) then
  1406. begin
  1407. { constant sets can be converted by changing the type only }
  1408. if (left.nodetype=setconstn) then
  1409. begin
  1410. left.resultdef:=resultdef;
  1411. result:=left;
  1412. left:=nil;
  1413. exit;
  1414. end;
  1415. if (tsetdef(resultdef).settype <> smallset) then
  1416. convtype:=tc_load_smallset
  1417. else
  1418. convtype := tc_normal_2_smallset;
  1419. exit;
  1420. end
  1421. else
  1422. begin
  1423. { Only leave when there is no conversion to do.
  1424. We can still need to call a conversion routine,
  1425. like the routine to convert a stringconstnode }
  1426. if convtype in [tc_equal,tc_not_possible] then
  1427. begin
  1428. left.resultdef:=resultdef;
  1429. if (nf_explicit in flags) and (left.nodetype = addrn) then
  1430. include(left.flags, nf_typedaddr);
  1431. result:=left;
  1432. left:=nil;
  1433. exit;
  1434. end;
  1435. end;
  1436. end;
  1437. te_convert_l1,
  1438. te_convert_l2,
  1439. te_convert_l3 :
  1440. begin
  1441. result := simplify;
  1442. if assigned(result) then
  1443. exit;
  1444. { nothing to do }
  1445. end;
  1446. te_convert_operator :
  1447. begin
  1448. include(current_procinfo.flags,pi_do_call);
  1449. inc(aprocdef.procsym.refs);
  1450. hp:=ccallnode.create(ccallparanode.create(left,nil),Tprocsym(aprocdef.procsym),nil,nil,[]);
  1451. { tell explicitly which def we must use !! (PM) }
  1452. tcallnode(hp).procdefinition:=aprocdef;
  1453. left:=nil;
  1454. result:=hp;
  1455. exit;
  1456. end;
  1457. te_incompatible :
  1458. begin
  1459. { Procedures have a resultdef of voiddef and functions of their
  1460. own resultdef. They will therefore always be incompatible with
  1461. a procvar. Because isconvertable cannot check for procedures we
  1462. use an extra check for them.}
  1463. if (left.nodetype=calln) and
  1464. (tcallnode(left).para_count=0) and
  1465. (resultdef.deftype=procvardef) and
  1466. (
  1467. (m_tp_procvar in current_settings.modeswitches) or
  1468. (m_mac_procvar in current_settings.modeswitches)
  1469. ) then
  1470. begin
  1471. if assigned(tcallnode(left).right) then
  1472. begin
  1473. { this is already a procvar, if it is really equal
  1474. is checked below }
  1475. convtype:=tc_equal;
  1476. hp:=tcallnode(left).right.getcopy;
  1477. currprocdef:=tabstractprocdef(hp.resultdef);
  1478. end
  1479. else
  1480. begin
  1481. convtype:=tc_proc_2_procvar;
  1482. currprocdef:=Tprocsym(Tcallnode(left).symtableprocentry).search_procdef_byprocvardef(Tprocvardef(resultdef));
  1483. hp:=cloadnode.create_procvar(tprocsym(tcallnode(left).symtableprocentry),
  1484. tprocdef(currprocdef),tcallnode(left).symtableproc);
  1485. if (tcallnode(left).symtableprocentry.owner.symtabletype=objectsymtable) then
  1486. begin
  1487. if assigned(tcallnode(left).methodpointer) then
  1488. tloadnode(hp).set_mp(tcallnode(left).get_load_methodpointer)
  1489. else
  1490. tloadnode(hp).set_mp(load_self_node);
  1491. end;
  1492. typecheckpass(hp);
  1493. end;
  1494. left.free;
  1495. left:=hp;
  1496. { Now check if the procedure we are going to assign to
  1497. the procvar, is compatible with the procvar's type }
  1498. if not(nf_explicit in flags) and
  1499. (proc_to_procvar_equal(currprocdef,tprocvardef(resultdef))=te_incompatible) then
  1500. IncompatibleTypes(left.resultdef,resultdef);
  1501. exit;
  1502. end;
  1503. { Handle explicit type conversions }
  1504. if nf_explicit in flags then
  1505. begin
  1506. { do common tc_equal cast }
  1507. convtype:=tc_equal;
  1508. { ordinal constants can be resized to 1,2,4,8 bytes }
  1509. if (left.nodetype=ordconstn) then
  1510. begin
  1511. { Insert typeconv for ordinal to the correct size first on left, after
  1512. that the other conversion can be done }
  1513. hdef:=nil;
  1514. case longint(resultdef.size) of
  1515. 1 :
  1516. hdef:=s8inttype;
  1517. 2 :
  1518. hdef:=s16inttype;
  1519. 4 :
  1520. hdef:=s32inttype;
  1521. 8 :
  1522. hdef:=s64inttype;
  1523. end;
  1524. { we need explicit, because it can also be an enum }
  1525. if assigned(hdef) then
  1526. inserttypeconv_internal(left,hdef)
  1527. else
  1528. CGMessage2(type_e_illegal_type_conversion,left.resultdef.GetTypeName,resultdef.GetTypeName);
  1529. end;
  1530. { check if the result could be in a register }
  1531. if (not(tstoreddef(resultdef).is_intregable) and
  1532. not(tstoreddef(resultdef).is_fpuregable)) or
  1533. ((left.resultdef.deftype = floatdef) and
  1534. (resultdef.deftype <> floatdef)) then
  1535. make_not_regable(left,vr_addr);
  1536. { class/interface to class/interface, with checkobject support }
  1537. if is_class_or_interface(resultdef) and
  1538. is_class_or_interface(left.resultdef) then
  1539. begin
  1540. { check if the types are related }
  1541. if not(nf_internal in flags) and
  1542. (not(tobjectdef(left.resultdef).is_related(tobjectdef(resultdef)))) and
  1543. (not(tobjectdef(resultdef).is_related(tobjectdef(left.resultdef)))) then
  1544. begin
  1545. { Give an error when typecasting class to interface, this is compatible
  1546. with delphi }
  1547. if is_interface(resultdef) and
  1548. not is_interface(left.resultdef) then
  1549. CGMessage2(type_e_classes_not_related,
  1550. FullTypeName(left.resultdef,resultdef),
  1551. FullTypeName(resultdef,left.resultdef))
  1552. else
  1553. CGMessage2(type_w_classes_not_related,
  1554. FullTypeName(left.resultdef,resultdef),
  1555. FullTypeName(resultdef,left.resultdef))
  1556. end;
  1557. { Add runtime check? }
  1558. if (cs_check_object in current_settings.localswitches) then
  1559. begin
  1560. { we can translate the typeconvnode to 'as' when
  1561. typecasting to a class or interface }
  1562. hp:=casnode.create(left,cloadvmtaddrnode.create(ctypenode.create(resultdef)));
  1563. left:=nil;
  1564. result:=hp;
  1565. exit;
  1566. end;
  1567. end
  1568. else
  1569. begin
  1570. { only if the same size or formal def }
  1571. if not(
  1572. (left.resultdef.deftype=formaldef) or
  1573. (
  1574. not(is_open_array(left.resultdef)) and
  1575. not(is_array_constructor(left.resultdef)) and
  1576. (left.resultdef.size=resultdef.size)
  1577. ) or
  1578. (
  1579. is_void(left.resultdef) and
  1580. (left.nodetype=derefn)
  1581. )
  1582. ) then
  1583. CGMessage2(type_e_illegal_type_conversion,left.resultdef.GetTypeName,resultdef.GetTypeName);
  1584. end;
  1585. end
  1586. else
  1587. IncompatibleTypes(left.resultdef,resultdef);
  1588. end;
  1589. else
  1590. internalerror(200211231);
  1591. end;
  1592. end;
  1593. { Give hint or warning for unportable code, exceptions are
  1594. - typecasts from constants
  1595. - void }
  1596. if not(nf_internal in flags) and
  1597. (left.nodetype<>ordconstn) and
  1598. not(is_void(left.resultdef)) and
  1599. (((left.resultdef.deftype=orddef) and
  1600. (resultdef.deftype in [pointerdef,procvardef,classrefdef])) or
  1601. ((resultdef.deftype=orddef) and
  1602. (left.resultdef.deftype in [pointerdef,procvardef,classrefdef]))) then
  1603. begin
  1604. { Give a warning when sizes don't match, because then info will be lost }
  1605. if left.resultdef.size=resultdef.size then
  1606. CGMessage(type_h_pointer_to_longint_conv_not_portable)
  1607. else
  1608. CGMessage(type_w_pointer_to_longint_conv_not_portable);
  1609. end;
  1610. result := simplify;
  1611. if assigned(result) then
  1612. exit;
  1613. { now call the resultdef helper to do constant folding }
  1614. result:=typecheck_call_helper(convtype);
  1615. end;
  1616. function ttypeconvnode.simplify: tnode;
  1617. var
  1618. hp: tnode;
  1619. begin
  1620. result := nil;
  1621. { Constant folding and other node transitions to
  1622. remove the typeconv node }
  1623. case left.nodetype of
  1624. realconstn :
  1625. begin
  1626. if (convtype = tc_real_2_currency) then
  1627. result := typecheck_real_to_currency
  1628. else if (convtype = tc_real_2_real) then
  1629. result := typecheck_real_to_real
  1630. else
  1631. exit;
  1632. if not(assigned(result)) then
  1633. begin
  1634. result := left;
  1635. left := nil;
  1636. end;
  1637. if (result.nodetype = realconstn) then
  1638. begin
  1639. result:=crealconstnode.create(trealconstnode(result).value_real,resultdef);
  1640. if ([nf_explicit,nf_internal] * flags <> []) then
  1641. include(result.flags, nf_explicit);
  1642. end;
  1643. end;
  1644. niln :
  1645. begin
  1646. { nil to ordinal node }
  1647. if (resultdef.deftype=orddef) then
  1648. begin
  1649. hp:=cordconstnode.create(0,resultdef,true);
  1650. if ([nf_explicit,nf_internal] * flags <> []) then
  1651. include(hp.flags, nf_explicit);
  1652. result:=hp;
  1653. exit;
  1654. end
  1655. else
  1656. { fold nil to any pointer type }
  1657. if (resultdef.deftype=pointerdef) then
  1658. begin
  1659. hp:=cnilnode.create;
  1660. hp.resultdef:=resultdef;
  1661. if ([nf_explicit,nf_internal] * flags <> []) then
  1662. include(hp.flags, nf_explicit);
  1663. result:=hp;
  1664. exit;
  1665. end
  1666. else
  1667. { remove typeconv after niln, but not when the result is a
  1668. methodpointer. The typeconv of the methodpointer will then
  1669. take care of updateing size of niln to OS_64 }
  1670. if not((resultdef.deftype=procvardef) and
  1671. (po_methodpointer in tprocvardef(resultdef).procoptions)) then
  1672. begin
  1673. left.resultdef:=resultdef;
  1674. if ([nf_explicit,nf_internal] * flags <> []) then
  1675. include(left.flags, nf_explicit);
  1676. result:=left;
  1677. left:=nil;
  1678. exit;
  1679. end;
  1680. end;
  1681. ordconstn :
  1682. begin
  1683. { ordinal contants can be directly converted }
  1684. { but not char to char because it is a widechar to char or via versa }
  1685. { which needs extra code to do the code page transistion }
  1686. { constant ordinal to pointer }
  1687. if (resultdef.deftype=pointerdef) and
  1688. (convtype<>tc_cchar_2_pchar) then
  1689. begin
  1690. hp:=cpointerconstnode.create(TConstPtrUInt(tordconstnode(left).value),resultdef);
  1691. if ([nf_explicit,nf_internal] * flags <> []) then
  1692. include(hp.flags, nf_explicit);
  1693. result:=hp;
  1694. exit;
  1695. end
  1696. else if is_ordinal(resultdef) and
  1697. not(convtype=tc_char_2_char) then
  1698. begin
  1699. { replace the resultdef and recheck the range }
  1700. left.resultdef:=resultdef;
  1701. if ([nf_explicit,nf_internal] * flags <> []) then
  1702. include(left.flags, nf_explicit);
  1703. testrange(left.resultdef,tordconstnode(left).value,(nf_explicit in flags));
  1704. result:=left;
  1705. left:=nil;
  1706. exit;
  1707. end;
  1708. end;
  1709. pointerconstn :
  1710. begin
  1711. { pointerconstn to any pointer is folded too }
  1712. if (resultdef.deftype=pointerdef) then
  1713. begin
  1714. left.resultdef:=resultdef;
  1715. if ([nf_explicit,nf_internal] * flags <> []) then
  1716. include(left.flags, nf_explicit);
  1717. result:=left;
  1718. left:=nil;
  1719. exit;
  1720. end
  1721. { constant pointer to ordinal }
  1722. else if is_ordinal(resultdef) then
  1723. begin
  1724. hp:=cordconstnode.create(TConstExprInt(tpointerconstnode(left).value),
  1725. resultdef,not(nf_explicit in flags));
  1726. if ([nf_explicit,nf_internal] * flags <> []) then
  1727. include(hp.flags, nf_explicit);
  1728. result:=hp;
  1729. exit;
  1730. end;
  1731. end;
  1732. end;
  1733. end;
  1734. procedure Ttypeconvnode.mark_write;
  1735. begin
  1736. left.mark_write;
  1737. end;
  1738. function ttypeconvnode.first_cord_to_pointer : tnode;
  1739. begin
  1740. result:=nil;
  1741. internalerror(200104043);
  1742. end;
  1743. function ttypeconvnode.first_int_to_int : tnode;
  1744. begin
  1745. first_int_to_int:=nil;
  1746. expectloc:=left.expectloc;
  1747. if not is_void(left.resultdef) then
  1748. begin
  1749. if (left.expectloc<>LOC_REGISTER) and
  1750. (resultdef.size>left.resultdef.size) then
  1751. expectloc:=LOC_REGISTER
  1752. else
  1753. if (left.expectloc=LOC_CREGISTER) and
  1754. (resultdef.size<left.resultdef.size) then
  1755. expectloc:=LOC_REGISTER;
  1756. end;
  1757. {$ifndef cpu64bit}
  1758. if is_64bit(resultdef) then
  1759. registersint:=max(registersint,2)
  1760. else
  1761. {$endif cpu64bit}
  1762. registersint:=max(registersint,1);
  1763. end;
  1764. function ttypeconvnode.first_cstring_to_pchar : tnode;
  1765. begin
  1766. result:=nil;
  1767. registersint:=1;
  1768. expectloc:=LOC_REGISTER;
  1769. end;
  1770. function ttypeconvnode.first_cstring_to_int : tnode;
  1771. begin
  1772. result:=nil;
  1773. internalerror(200510014);
  1774. end;
  1775. function ttypeconvnode.first_string_to_chararray : tnode;
  1776. begin
  1777. first_string_to_chararray:=nil;
  1778. expectloc:=left.expectloc;
  1779. end;
  1780. function ttypeconvnode.first_char_to_string : tnode;
  1781. begin
  1782. first_char_to_string:=nil;
  1783. expectloc:=LOC_REFERENCE;
  1784. end;
  1785. function ttypeconvnode.first_nothing : tnode;
  1786. begin
  1787. first_nothing:=nil;
  1788. end;
  1789. function ttypeconvnode.first_array_to_pointer : tnode;
  1790. begin
  1791. first_array_to_pointer:=nil;
  1792. if registersint<1 then
  1793. registersint:=1;
  1794. expectloc:=LOC_REGISTER;
  1795. end;
  1796. function ttypeconvnode.first_int_to_real: tnode;
  1797. var
  1798. fname: string[32];
  1799. typname : string[12];
  1800. begin
  1801. { Get the type name }
  1802. { Normally the typename should be one of the following:
  1803. single, double - carl
  1804. }
  1805. typname := lower(pbestrealtype^.GetTypeName);
  1806. { converting a 64bit integer to a float requires a helper }
  1807. if is_64bit(left.resultdef) then
  1808. begin
  1809. if is_signed(left.resultdef) then
  1810. fname := 'fpc_int64_to_'+typname
  1811. else
  1812. {$warning generic conversion from int to float does not support unsigned integers}
  1813. fname := 'fpc_int64_to_'+typname;
  1814. result := ccallnode.createintern(fname,ccallparanode.create(
  1815. left,nil));
  1816. left:=nil;
  1817. firstpass(result);
  1818. exit;
  1819. end
  1820. else
  1821. { other integers are supposed to be 32 bit }
  1822. begin
  1823. {$warning generic conversion from int to float does not support unsigned integers}
  1824. if is_signed(left.resultdef) then
  1825. fname := 'fpc_longint_to_'+typname
  1826. else
  1827. fname := 'fpc_longint_to_'+typname;
  1828. result := ccallnode.createintern(fname,ccallparanode.create(
  1829. left,nil));
  1830. left:=nil;
  1831. firstpass(result);
  1832. exit;
  1833. end;
  1834. end;
  1835. function ttypeconvnode.first_real_to_real : tnode;
  1836. begin
  1837. {$ifdef cpufpemu}
  1838. if cs_fp_emulation in current_settings.moduleswitches then
  1839. begin
  1840. if target_info.system in system_wince then
  1841. begin
  1842. case tfloatdef(left.resultdef).typ of
  1843. s32real:
  1844. case tfloatdef(resultdef).typ of
  1845. s64real:
  1846. result:=ccallnode.createintern('STOD',ccallparanode.create(left,nil));
  1847. s32real:
  1848. begin
  1849. result:=left;
  1850. left:=nil;
  1851. end;
  1852. else
  1853. internalerror(2005082704);
  1854. end;
  1855. s64real:
  1856. case tfloatdef(resultdef).typ of
  1857. s32real:
  1858. result:=ccallnode.createintern('DTOS',ccallparanode.create(left,nil));
  1859. s64real:
  1860. begin
  1861. result:=left;
  1862. left:=nil;
  1863. end;
  1864. else
  1865. internalerror(2005082703);
  1866. end;
  1867. else
  1868. internalerror(2005082702);
  1869. end;
  1870. left:=nil;
  1871. firstpass(result);
  1872. exit;
  1873. end
  1874. else
  1875. begin
  1876. case tfloatdef(left.resultdef).typ of
  1877. s32real:
  1878. case tfloatdef(resultdef).typ of
  1879. s64real:
  1880. result:=ctypeconvnode.create_explicit(ccallnode.createintern('float32_to_float64',ccallparanode.create(
  1881. ctypeconvnode.create_internal(left,search_system_type('FLOAT32REC').typedef),nil)),resultdef);
  1882. s32real:
  1883. begin
  1884. result:=left;
  1885. left:=nil;
  1886. end;
  1887. else
  1888. internalerror(200610151);
  1889. end;
  1890. s64real:
  1891. case tfloatdef(resultdef).typ of
  1892. s32real:
  1893. result:=ctypeconvnode.create_explicit(ccallnode.createintern('float64_to_float32',ccallparanode.create(
  1894. ctypeconvnode.create_internal(left,search_system_type('FLOAT64').typedef),nil)),resultdef);
  1895. s64real:
  1896. begin
  1897. result:=left;
  1898. left:=nil;
  1899. end;
  1900. else
  1901. internalerror(200610152);
  1902. end;
  1903. else
  1904. internalerror(200610153);
  1905. end;
  1906. left:=nil;
  1907. firstpass(result);
  1908. exit;
  1909. end;
  1910. end
  1911. else
  1912. {$endif cpufpemu}
  1913. begin
  1914. first_real_to_real:=nil;
  1915. if registersfpu<1 then
  1916. registersfpu:=1;
  1917. expectloc:=LOC_FPUREGISTER;
  1918. end;
  1919. end;
  1920. function ttypeconvnode.first_pointer_to_array : tnode;
  1921. begin
  1922. first_pointer_to_array:=nil;
  1923. if registersint<1 then
  1924. registersint:=1;
  1925. expectloc:=LOC_REFERENCE;
  1926. end;
  1927. function ttypeconvnode.first_cchar_to_pchar : tnode;
  1928. begin
  1929. first_cchar_to_pchar:=nil;
  1930. internalerror(200104021);
  1931. end;
  1932. function ttypeconvnode.first_bool_to_int : tnode;
  1933. begin
  1934. first_bool_to_int:=nil;
  1935. { byte(boolean) or word(wordbool) or longint(longbool) must
  1936. be accepted for var parameters }
  1937. if (nf_explicit in flags) and
  1938. (left.resultdef.size=resultdef.size) and
  1939. (left.expectloc in [LOC_REFERENCE,LOC_CREFERENCE,LOC_CREGISTER]) then
  1940. exit;
  1941. { when converting to 64bit, first convert to a 32bit int and then }
  1942. { convert to a 64bit int (only necessary for 32bit processors) (JM) }
  1943. if resultdef.size > sizeof(aint) then
  1944. begin
  1945. result := ctypeconvnode.create_internal(left,u32inttype);
  1946. result := ctypeconvnode.create(result,resultdef);
  1947. left := nil;
  1948. firstpass(result);
  1949. exit;
  1950. end;
  1951. expectloc:=LOC_REGISTER;
  1952. if registersint<1 then
  1953. registersint:=1;
  1954. end;
  1955. function ttypeconvnode.first_int_to_bool : tnode;
  1956. begin
  1957. first_int_to_bool:=nil;
  1958. { byte(boolean) or word(wordbool) or longint(longbool) must
  1959. be accepted for var parameters }
  1960. if (nf_explicit in flags) and
  1961. (left.resultdef.size=resultdef.size) and
  1962. (left.expectloc in [LOC_REFERENCE,LOC_CREFERENCE,LOC_CREGISTER]) then
  1963. exit;
  1964. expectloc:=LOC_REGISTER;
  1965. { need if bool to bool !!
  1966. not very nice !!
  1967. insertypeconv(left,s32inttype);
  1968. left.explizit:=true;
  1969. firstpass(left); }
  1970. if registersint<1 then
  1971. registersint:=1;
  1972. end;
  1973. function ttypeconvnode.first_bool_to_bool : tnode;
  1974. begin
  1975. first_bool_to_bool:=nil;
  1976. if (left.expectloc in [LOC_FLAGS,LOC_JUMP]) then
  1977. expectloc := left.expectloc
  1978. else
  1979. begin
  1980. expectloc:=LOC_REGISTER;
  1981. if registersint<1 then
  1982. registersint:=1;
  1983. end;
  1984. end;
  1985. function ttypeconvnode.first_char_to_char : tnode;
  1986. begin
  1987. first_char_to_char:=first_int_to_int;
  1988. end;
  1989. function ttypeconvnode.first_proc_to_procvar : tnode;
  1990. begin
  1991. first_proc_to_procvar:=nil;
  1992. if tabstractprocdef(resultdef).is_addressonly then
  1993. begin
  1994. registersint:=left.registersint;
  1995. if registersint<1 then
  1996. registersint:=1;
  1997. expectloc:=LOC_REGISTER;
  1998. end
  1999. else
  2000. begin
  2001. if not(left.expectloc in [LOC_CREFERENCE,LOC_REFERENCE]) then
  2002. CGMessage(parser_e_illegal_expression);
  2003. registersint:=left.registersint;
  2004. expectloc:=left.expectloc
  2005. end
  2006. end;
  2007. function ttypeconvnode.first_load_smallset : tnode;
  2008. var
  2009. srsym: ttypesym;
  2010. p: tcallparanode;
  2011. begin
  2012. srsym:=search_system_type('FPC_SMALL_SET');
  2013. p := ccallparanode.create(left,nil);
  2014. { reused }
  2015. left := nil;
  2016. { convert parameter explicitely to fpc_small_set }
  2017. p.left := ctypeconvnode.create_internal(p.left,srsym.typedef);
  2018. { create call, adjust resultdef }
  2019. result :=
  2020. ccallnode.createinternres('fpc_set_load_small',p,resultdef);
  2021. firstpass(result);
  2022. end;
  2023. function ttypeconvnode.first_ansistring_to_pchar : tnode;
  2024. begin
  2025. first_ansistring_to_pchar:=nil;
  2026. expectloc:=LOC_REGISTER;
  2027. if registersint<1 then
  2028. registersint:=1;
  2029. end;
  2030. function ttypeconvnode.first_arrayconstructor_to_set : tnode;
  2031. begin
  2032. first_arrayconstructor_to_set:=nil;
  2033. internalerror(200104022);
  2034. end;
  2035. function ttypeconvnode.first_class_to_intf : tnode;
  2036. begin
  2037. first_class_to_intf:=nil;
  2038. expectloc:=LOC_REGISTER;
  2039. if registersint<1 then
  2040. registersint:=1;
  2041. end;
  2042. function ttypeconvnode._first_int_to_int : tnode;
  2043. begin
  2044. result:=first_int_to_int;
  2045. end;
  2046. function ttypeconvnode._first_cstring_to_pchar : tnode;
  2047. begin
  2048. result:=first_cstring_to_pchar;
  2049. end;
  2050. function ttypeconvnode._first_cstring_to_int : tnode;
  2051. begin
  2052. result:=first_cstring_to_int;
  2053. end;
  2054. function ttypeconvnode._first_string_to_chararray : tnode;
  2055. begin
  2056. result:=first_string_to_chararray;
  2057. end;
  2058. function ttypeconvnode._first_char_to_string : tnode;
  2059. begin
  2060. result:=first_char_to_string;
  2061. end;
  2062. function ttypeconvnode._first_nothing : tnode;
  2063. begin
  2064. result:=first_nothing;
  2065. end;
  2066. function ttypeconvnode._first_array_to_pointer : tnode;
  2067. begin
  2068. result:=first_array_to_pointer;
  2069. end;
  2070. function ttypeconvnode._first_int_to_real : tnode;
  2071. begin
  2072. result:=first_int_to_real;
  2073. end;
  2074. function ttypeconvnode._first_real_to_real : tnode;
  2075. begin
  2076. result:=first_real_to_real;
  2077. end;
  2078. function ttypeconvnode._first_pointer_to_array : tnode;
  2079. begin
  2080. result:=first_pointer_to_array;
  2081. end;
  2082. function ttypeconvnode._first_cchar_to_pchar : tnode;
  2083. begin
  2084. result:=first_cchar_to_pchar;
  2085. end;
  2086. function ttypeconvnode._first_bool_to_int : tnode;
  2087. begin
  2088. result:=first_bool_to_int;
  2089. end;
  2090. function ttypeconvnode._first_int_to_bool : tnode;
  2091. begin
  2092. result:=first_int_to_bool;
  2093. end;
  2094. function ttypeconvnode._first_bool_to_bool : tnode;
  2095. begin
  2096. result:=first_bool_to_bool;
  2097. end;
  2098. function ttypeconvnode._first_proc_to_procvar : tnode;
  2099. begin
  2100. result:=first_proc_to_procvar;
  2101. end;
  2102. function ttypeconvnode._first_load_smallset : tnode;
  2103. begin
  2104. result:=first_load_smallset;
  2105. end;
  2106. function ttypeconvnode._first_cord_to_pointer : tnode;
  2107. begin
  2108. result:=first_cord_to_pointer;
  2109. end;
  2110. function ttypeconvnode._first_ansistring_to_pchar : tnode;
  2111. begin
  2112. result:=first_ansistring_to_pchar;
  2113. end;
  2114. function ttypeconvnode._first_arrayconstructor_to_set : tnode;
  2115. begin
  2116. result:=first_arrayconstructor_to_set;
  2117. end;
  2118. function ttypeconvnode._first_class_to_intf : tnode;
  2119. begin
  2120. result:=first_class_to_intf;
  2121. end;
  2122. function ttypeconvnode._first_char_to_char : tnode;
  2123. begin
  2124. result:=first_char_to_char;
  2125. end;
  2126. function ttypeconvnode.first_call_helper(c : tconverttype) : tnode;
  2127. const
  2128. firstconvert : array[tconverttype] of pointer = (
  2129. nil, { none }
  2130. @ttypeconvnode._first_nothing, {equal}
  2131. @ttypeconvnode._first_nothing, {not_possible}
  2132. nil, { removed in typecheck_string_to_string }
  2133. @ttypeconvnode._first_char_to_string,
  2134. @ttypeconvnode._first_nothing, { char_2_chararray, needs nothing extra }
  2135. nil, { removed in typecheck_chararray_to_string }
  2136. @ttypeconvnode._first_cchar_to_pchar,
  2137. @ttypeconvnode._first_cstring_to_pchar,
  2138. @ttypeconvnode._first_cstring_to_int,
  2139. @ttypeconvnode._first_ansistring_to_pchar,
  2140. @ttypeconvnode._first_string_to_chararray,
  2141. nil, { removed in typecheck_chararray_to_string }
  2142. @ttypeconvnode._first_array_to_pointer,
  2143. @ttypeconvnode._first_pointer_to_array,
  2144. @ttypeconvnode._first_int_to_int,
  2145. @ttypeconvnode._first_int_to_bool,
  2146. nil, { removed in typecheck_int_to_string }
  2147. @ttypeconvnode._first_bool_to_bool,
  2148. @ttypeconvnode._first_bool_to_int,
  2149. @ttypeconvnode._first_real_to_real,
  2150. @ttypeconvnode._first_int_to_real,
  2151. nil, { removed in typecheck_real_to_currency }
  2152. @ttypeconvnode._first_proc_to_procvar,
  2153. @ttypeconvnode._first_arrayconstructor_to_set,
  2154. @ttypeconvnode._first_load_smallset,
  2155. @ttypeconvnode._first_cord_to_pointer,
  2156. @ttypeconvnode._first_nothing,
  2157. @ttypeconvnode._first_nothing,
  2158. @ttypeconvnode._first_class_to_intf,
  2159. @ttypeconvnode._first_char_to_char,
  2160. @ttypeconvnode._first_nothing,
  2161. @ttypeconvnode._first_nothing,
  2162. nil,
  2163. nil,
  2164. nil,
  2165. nil,
  2166. nil,
  2167. nil,
  2168. nil,
  2169. nil
  2170. );
  2171. type
  2172. tprocedureofobject = function : tnode of object;
  2173. var
  2174. r : packed record
  2175. proc : pointer;
  2176. obj : pointer;
  2177. end;
  2178. begin
  2179. { this is a little bit dirty but it works }
  2180. { and should be quite portable too }
  2181. r.proc:=firstconvert[c];
  2182. r.obj:=self;
  2183. if not assigned(r.proc) then
  2184. internalerror(200312081);
  2185. first_call_helper:=tprocedureofobject(r)()
  2186. end;
  2187. function ttypeconvnode.pass_1 : tnode;
  2188. begin
  2189. result:=nil;
  2190. firstpass(left);
  2191. if codegenerror then
  2192. exit;
  2193. { load the value_str from the left part }
  2194. registersint:=left.registersint;
  2195. registersfpu:=left.registersfpu;
  2196. {$ifdef SUPPORT_MMX}
  2197. registersmmx:=left.registersmmx;
  2198. {$endif}
  2199. expectloc:=left.expectloc;
  2200. result:=first_call_helper(convtype);
  2201. end;
  2202. function ttypeconvnode.assign_allowed:boolean;
  2203. begin
  2204. result:=(convtype=tc_equal) or
  2205. { typecasting from void is always allowed }
  2206. is_void(left.resultdef) or
  2207. (left.resultdef.deftype=formaldef) or
  2208. { int 2 int with same size reuses same location, or for
  2209. tp7 mode also allow size < orignal size }
  2210. (
  2211. (convtype=tc_int_2_int) and
  2212. (
  2213. (resultdef.size=left.resultdef.size) or
  2214. ((m_tp7 in current_settings.modeswitches) and
  2215. (resultdef.size<left.resultdef.size))
  2216. )
  2217. ) or
  2218. { int 2 bool/bool 2 int, explicit typecast, see also nx86cnv }
  2219. ((convtype in [tc_int_2_bool,tc_bool_2_int]) and
  2220. (nf_explicit in flags) and
  2221. (resultdef.size=left.resultdef.size));
  2222. { When using only a part of the value it can't be in a register since
  2223. that will load the value in a new register first }
  2224. if (resultdef.size<left.resultdef.size) then
  2225. make_not_regable(left,vr_addr);
  2226. end;
  2227. function ttypeconvnode.docompare(p: tnode) : boolean;
  2228. begin
  2229. docompare :=
  2230. inherited docompare(p) and
  2231. (convtype = ttypeconvnode(p).convtype);
  2232. end;
  2233. procedure ttypeconvnode._second_int_to_int;
  2234. begin
  2235. second_int_to_int;
  2236. end;
  2237. procedure ttypeconvnode._second_string_to_string;
  2238. begin
  2239. second_string_to_string;
  2240. end;
  2241. procedure ttypeconvnode._second_cstring_to_pchar;
  2242. begin
  2243. second_cstring_to_pchar;
  2244. end;
  2245. procedure ttypeconvnode._second_cstring_to_int;
  2246. begin
  2247. second_cstring_to_int;
  2248. end;
  2249. procedure ttypeconvnode._second_string_to_chararray;
  2250. begin
  2251. second_string_to_chararray;
  2252. end;
  2253. procedure ttypeconvnode._second_array_to_pointer;
  2254. begin
  2255. second_array_to_pointer;
  2256. end;
  2257. procedure ttypeconvnode._second_pointer_to_array;
  2258. begin
  2259. second_pointer_to_array;
  2260. end;
  2261. procedure ttypeconvnode._second_chararray_to_string;
  2262. begin
  2263. second_chararray_to_string;
  2264. end;
  2265. procedure ttypeconvnode._second_char_to_string;
  2266. begin
  2267. second_char_to_string;
  2268. end;
  2269. procedure ttypeconvnode._second_int_to_real;
  2270. begin
  2271. second_int_to_real;
  2272. end;
  2273. procedure ttypeconvnode._second_real_to_real;
  2274. begin
  2275. second_real_to_real;
  2276. end;
  2277. procedure ttypeconvnode._second_cord_to_pointer;
  2278. begin
  2279. second_cord_to_pointer;
  2280. end;
  2281. procedure ttypeconvnode._second_proc_to_procvar;
  2282. begin
  2283. second_proc_to_procvar;
  2284. end;
  2285. procedure ttypeconvnode._second_bool_to_int;
  2286. begin
  2287. second_bool_to_int;
  2288. end;
  2289. procedure ttypeconvnode._second_int_to_bool;
  2290. begin
  2291. second_int_to_bool;
  2292. end;
  2293. procedure ttypeconvnode._second_bool_to_bool;
  2294. begin
  2295. second_bool_to_bool;
  2296. end;
  2297. procedure ttypeconvnode._second_load_smallset;
  2298. begin
  2299. second_load_smallset;
  2300. end;
  2301. procedure ttypeconvnode._second_ansistring_to_pchar;
  2302. begin
  2303. second_ansistring_to_pchar;
  2304. end;
  2305. procedure ttypeconvnode._second_class_to_intf;
  2306. begin
  2307. second_class_to_intf;
  2308. end;
  2309. procedure ttypeconvnode._second_char_to_char;
  2310. begin
  2311. second_char_to_char;
  2312. end;
  2313. procedure ttypeconvnode._second_nothing;
  2314. begin
  2315. second_nothing;
  2316. end;
  2317. procedure ttypeconvnode.second_call_helper(c : tconverttype);
  2318. const
  2319. secondconvert : array[tconverttype] of pointer = (
  2320. @ttypeconvnode._second_nothing, {none}
  2321. @ttypeconvnode._second_nothing, {equal}
  2322. @ttypeconvnode._second_nothing, {not_possible}
  2323. @ttypeconvnode._second_nothing, {second_string_to_string, handled in resultdef pass }
  2324. @ttypeconvnode._second_char_to_string,
  2325. @ttypeconvnode._second_nothing, {char_to_charray}
  2326. @ttypeconvnode._second_nothing, { pchar_to_string, handled in resultdef pass }
  2327. @ttypeconvnode._second_nothing, {cchar_to_pchar}
  2328. @ttypeconvnode._second_cstring_to_pchar,
  2329. @ttypeconvnode._second_cstring_to_int,
  2330. @ttypeconvnode._second_ansistring_to_pchar,
  2331. @ttypeconvnode._second_string_to_chararray,
  2332. @ttypeconvnode._second_nothing, { chararray_to_string, handled in resultdef pass }
  2333. @ttypeconvnode._second_array_to_pointer,
  2334. @ttypeconvnode._second_pointer_to_array,
  2335. @ttypeconvnode._second_int_to_int,
  2336. @ttypeconvnode._second_int_to_bool,
  2337. @ttypeconvnode._second_nothing, { int_to_string, handled in resultdef pass }
  2338. @ttypeconvnode._second_bool_to_bool,
  2339. @ttypeconvnode._second_bool_to_int,
  2340. @ttypeconvnode._second_real_to_real,
  2341. @ttypeconvnode._second_int_to_real,
  2342. @ttypeconvnode._second_nothing, { real_to_currency, handled in resultdef pass }
  2343. @ttypeconvnode._second_proc_to_procvar,
  2344. @ttypeconvnode._second_nothing, { arrayconstructor_to_set }
  2345. @ttypeconvnode._second_nothing, { second_load_smallset, handled in first pass }
  2346. @ttypeconvnode._second_cord_to_pointer,
  2347. @ttypeconvnode._second_nothing, { interface 2 string }
  2348. @ttypeconvnode._second_nothing, { interface 2 guid }
  2349. @ttypeconvnode._second_class_to_intf,
  2350. @ttypeconvnode._second_char_to_char,
  2351. @ttypeconvnode._second_nothing, { normal_2_smallset }
  2352. @ttypeconvnode._second_nothing, { dynarray_2_openarray }
  2353. @ttypeconvnode._second_nothing, { pwchar_2_string }
  2354. @ttypeconvnode._second_nothing, { variant_2_dynarray }
  2355. @ttypeconvnode._second_nothing, { dynarray_2_variant}
  2356. @ttypeconvnode._second_nothing, { variant_2_enum }
  2357. @ttypeconvnode._second_nothing, { enum_2_variant }
  2358. @ttypeconvnode._second_nothing, { variant_2_interface }
  2359. @ttypeconvnode._second_nothing, { interface_2_variant }
  2360. @ttypeconvnode._second_nothing { array_2_dynarray }
  2361. );
  2362. type
  2363. tprocedureofobject = procedure of object;
  2364. var
  2365. r : packed record
  2366. proc : pointer;
  2367. obj : pointer;
  2368. end;
  2369. begin
  2370. { this is a little bit dirty but it works }
  2371. { and should be quite portable too }
  2372. r.proc:=secondconvert[c];
  2373. r.obj:=self;
  2374. tprocedureofobject(r)();
  2375. end;
  2376. {*****************************************************************************
  2377. TISNODE
  2378. *****************************************************************************}
  2379. constructor tisnode.create(l,r : tnode);
  2380. begin
  2381. inherited create(isn,l,r);
  2382. end;
  2383. function tisnode.pass_typecheck:tnode;
  2384. var
  2385. paras: tcallparanode;
  2386. begin
  2387. result:=nil;
  2388. typecheckpass(left);
  2389. typecheckpass(right);
  2390. set_varstate(left,vs_read,[vsf_must_be_valid]);
  2391. set_varstate(right,vs_read,[vsf_must_be_valid]);
  2392. if codegenerror then
  2393. exit;
  2394. if (right.resultdef.deftype=classrefdef) then
  2395. begin
  2396. { left must be a class }
  2397. if is_class(left.resultdef) then
  2398. begin
  2399. { the operands must be related }
  2400. if (not(tobjectdef(left.resultdef).is_related(
  2401. tobjectdef(tclassrefdef(right.resultdef).pointeddef)))) and
  2402. (not(tobjectdef(tclassrefdef(right.resultdef).pointeddef).is_related(
  2403. tobjectdef(left.resultdef)))) then
  2404. CGMessage2(type_e_classes_not_related,left.resultdef.typename,
  2405. tclassrefdef(right.resultdef).pointeddef.typename);
  2406. end
  2407. else
  2408. CGMessage1(type_e_class_type_expected,left.resultdef.typename);
  2409. { call fpc_do_is helper }
  2410. paras := ccallparanode.create(
  2411. left,
  2412. ccallparanode.create(
  2413. right,nil));
  2414. result := ccallnode.createintern('fpc_do_is',paras);
  2415. left := nil;
  2416. right := nil;
  2417. end
  2418. else if is_interface(right.resultdef) then
  2419. begin
  2420. { left is a class }
  2421. if is_class(left.resultdef) then
  2422. begin
  2423. { the operands must be related }
  2424. if not(assigned(tobjectdef(left.resultdef).implementedinterfaces) and
  2425. (tobjectdef(left.resultdef).implementedinterfaces.searchintf(right.resultdef)<>-1)) then
  2426. CGMessage2(type_e_classes_not_related,
  2427. FullTypeName(left.resultdef,right.resultdef),
  2428. FullTypeName(right.resultdef,left.resultdef))
  2429. end
  2430. { left is an interface }
  2431. else if is_interface(left.resultdef) then
  2432. begin
  2433. { the operands must be related }
  2434. if (not(tobjectdef(left.resultdef).is_related(tobjectdef(right.resultdef)))) and
  2435. (not(tobjectdef(right.resultdef).is_related(tobjectdef(left.resultdef)))) then
  2436. CGMessage2(type_e_classes_not_related,
  2437. FullTypeName(left.resultdef,right.resultdef),
  2438. FullTypeName(right.resultdef,left.resultdef));
  2439. end
  2440. else
  2441. CGMessage1(type_e_class_type_expected,left.resultdef.typename);
  2442. { call fpc_do_is helper }
  2443. paras := ccallparanode.create(
  2444. left,
  2445. ccallparanode.create(
  2446. right,nil));
  2447. result := ccallnode.createintern('fpc_do_is',paras);
  2448. left := nil;
  2449. right := nil;
  2450. end
  2451. else
  2452. CGMessage1(type_e_class_or_interface_type_expected,right.resultdef.typename);
  2453. resultdef:=booltype;
  2454. end;
  2455. function tisnode.pass_1 : tnode;
  2456. begin
  2457. internalerror(200204254);
  2458. result:=nil;
  2459. end;
  2460. { dummy pass_2, it will never be called, but we need one since }
  2461. { you can't instantiate an abstract class }
  2462. procedure tisnode.pass_generate_code;
  2463. begin
  2464. end;
  2465. {*****************************************************************************
  2466. TASNODE
  2467. *****************************************************************************}
  2468. constructor tasnode.create(l,r : tnode);
  2469. begin
  2470. inherited create(asn,l,r);
  2471. call := nil;
  2472. end;
  2473. destructor tasnode.destroy;
  2474. begin
  2475. call.free;
  2476. inherited destroy;
  2477. end;
  2478. function tasnode.pass_typecheck:tnode;
  2479. var
  2480. hp : tnode;
  2481. begin
  2482. result:=nil;
  2483. typecheckpass(right);
  2484. typecheckpass(left);
  2485. set_varstate(right,vs_read,[vsf_must_be_valid]);
  2486. set_varstate(left,vs_read,[vsf_must_be_valid]);
  2487. if codegenerror then
  2488. exit;
  2489. if (right.resultdef.deftype=classrefdef) then
  2490. begin
  2491. { left must be a class }
  2492. if is_class(left.resultdef) then
  2493. begin
  2494. { the operands must be related }
  2495. if (not(tobjectdef(left.resultdef).is_related(
  2496. tobjectdef(tclassrefdef(right.resultdef).pointeddef)))) and
  2497. (not(tobjectdef(tclassrefdef(right.resultdef).pointeddef).is_related(
  2498. tobjectdef(left.resultdef)))) then
  2499. CGMessage2(type_e_classes_not_related,
  2500. FullTypeName(left.resultdef,tclassrefdef(right.resultdef).pointeddef),
  2501. FullTypeName(tclassrefdef(right.resultdef).pointeddef,left.resultdef));
  2502. end
  2503. else
  2504. CGMessage1(type_e_class_type_expected,left.resultdef.typename);
  2505. resultdef:=tclassrefdef(right.resultdef).pointeddef;
  2506. end
  2507. else if is_interface(right.resultdef) then
  2508. begin
  2509. { left is a class }
  2510. if not(is_class(left.resultdef) or
  2511. is_interfacecom(left.resultdef)) then
  2512. CGMessage1(type_e_class_or_cominterface_type_expected,left.resultdef.typename);
  2513. resultdef:=right.resultdef;
  2514. { load the GUID of the interface }
  2515. if (right.nodetype=typen) then
  2516. begin
  2517. if assigned(tobjectdef(right.resultdef).iidguid) then
  2518. begin
  2519. hp:=cguidconstnode.create(tobjectdef(right.resultdef).iidguid^);
  2520. right.free;
  2521. right:=hp;
  2522. end
  2523. else
  2524. internalerror(200206282);
  2525. typecheckpass(right);
  2526. end;
  2527. end
  2528. else
  2529. CGMessage1(type_e_class_or_interface_type_expected,right.resultdef.typename);
  2530. end;
  2531. function tasnode.dogetcopy: tnode;
  2532. begin
  2533. result := inherited dogetcopy;
  2534. if assigned(call) then
  2535. tasnode(result).call := call.getcopy
  2536. else
  2537. tasnode(result).call := nil;
  2538. end;
  2539. function tasnode.pass_1 : tnode;
  2540. var
  2541. procname: string;
  2542. begin
  2543. result:=nil;
  2544. if not assigned(call) then
  2545. begin
  2546. if is_class(left.resultdef) and
  2547. (right.resultdef.deftype=classrefdef) then
  2548. call := ccallnode.createinternres('fpc_do_as',
  2549. ccallparanode.create(left,ccallparanode.create(right,nil)),
  2550. resultdef)
  2551. else
  2552. begin
  2553. if is_class(left.resultdef) then
  2554. procname := 'fpc_class_as_intf'
  2555. else
  2556. procname := 'fpc_intf_as';
  2557. call := ccallnode.createintern(procname,
  2558. ccallparanode.create(right,ccallparanode.create(left,nil)));
  2559. call := ctypeconvnode.create_internal(call,resultdef);
  2560. end;
  2561. left := nil;
  2562. right := nil;
  2563. firstpass(call);
  2564. if codegenerror then
  2565. exit;
  2566. expectloc:=call.expectloc;
  2567. registersint:=call.registersint;
  2568. registersfpu:=call.registersfpu;
  2569. {$ifdef SUPPORT_MMX}
  2570. registersmmx:=call.registersmmx;
  2571. {$endif SUPPORT_MMX}
  2572. end;
  2573. end;
  2574. begin
  2575. ctypeconvnode:=ttypeconvnode;
  2576. casnode:=tasnode;
  2577. cisnode:=tisnode;
  2578. end.