ngtcon.pas 80 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188
  1. {
  2. Copyright (c) 1998-2011 by Florian Klaempfl, Jonas Maebe
  3. Generates code/nodes for typed constant declarations
  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 ngtcon;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. globtype,cclasses,constexp,
  22. aasmbase,aasmdata,aasmtai,aasmcnst,
  23. node,nbas,
  24. symconst, symtype, symbase, symdef,symsym;
  25. type
  26. ttypedconstbuilder = class
  27. protected
  28. current_old_block_type : tblock_type;
  29. tcsym: tstaticvarsym;
  30. { this procedure reads typed constants }
  31. procedure read_typed_const_data(def:tdef);
  32. procedure parse_orddef(def: torddef);
  33. procedure parse_floatdef(def: tfloatdef);
  34. procedure parse_classrefdef(def: tclassrefdef);
  35. procedure parse_pointerdef(def: tpointerdef);
  36. procedure parse_setdef(def: tsetdef);
  37. procedure parse_enumdef(def: tenumdef);
  38. procedure parse_stringdef(def: tstringdef);
  39. procedure parse_arraydef(def:tarraydef);virtual;abstract;
  40. procedure parse_procvardef(def:tprocvardef);virtual;abstract;
  41. procedure parse_recorddef(def:trecorddef);virtual;abstract;
  42. procedure parse_objectdef(def:tobjectdef);virtual;abstract;
  43. procedure tc_emit_orddef(def: torddef; var node: tnode);virtual;abstract;
  44. procedure tc_emit_floatdef(def: tfloatdef; var node: tnode);virtual;abstract;
  45. procedure tc_emit_classrefdef(def: tclassrefdef; var node: tnode);virtual;abstract;
  46. procedure tc_emit_pointerdef(def: tpointerdef; var node: tnode);virtual;abstract;
  47. procedure tc_emit_setdef(def: tsetdef; var node: tnode);virtual;abstract;
  48. procedure tc_emit_enumdef(def: tenumdef; var node: tnode);virtual;abstract;
  49. procedure tc_emit_stringdef(def: tstringdef; var node: tnode);virtual;abstract;
  50. public
  51. constructor create(sym: tstaticvarsym);
  52. end;
  53. ttypedconstbuilderclass = class of ttypedconstbuilder;
  54. { should be changed into nested type of tasmlisttypedconstbuilder when
  55. possible }
  56. tbitpackedval = record
  57. curval, nextval: aword;
  58. curbitoffset: smallint;
  59. loadbitsize,packedbitsize: byte;
  60. end;
  61. tasmlisttypedconstbuilder = class(ttypedconstbuilder)
  62. private
  63. fsym: tstaticvarsym;
  64. curoffset: asizeint;
  65. function parse_single_packed_const(def: tdef; var bp: tbitpackedval): boolean;
  66. procedure flush_packed_value(var bp: tbitpackedval);
  67. protected
  68. ftcb: ttai_typedconstbuilder;
  69. fdatalist: tasmlist;
  70. procedure parse_packed_array_def(def: tarraydef);
  71. procedure parse_arraydef(def:tarraydef);override;
  72. procedure parse_procvardef(def:tprocvardef);override;
  73. procedure parse_recorddef(def:trecorddef);override;
  74. procedure parse_objectdef(def:tobjectdef);override;
  75. procedure tc_emit_orddef(def: torddef; var node: tnode);override;
  76. procedure tc_emit_floatdef(def: tfloatdef; var node: tnode); override;
  77. procedure tc_emit_classrefdef(def: tclassrefdef; var node: tnode);override;
  78. procedure tc_emit_pointerdef(def: tpointerdef; var node: tnode);override;
  79. procedure tc_emit_setdef(def: tsetdef; var node: tnode);override;
  80. procedure tc_emit_enumdef(def: tenumdef; var node: tnode);override;
  81. procedure tc_emit_stringdef(def: tstringdef; var node: tnode);override;
  82. public
  83. constructor create(sym: tstaticvarsym);virtual;
  84. destructor Destroy; override;
  85. procedure parse_into_asmlist;
  86. { the asmlist containing the definition of the parsed entity and another
  87. one containing the data generated for that same entity (e.g. the
  88. string data referenced by an ansistring constant) }
  89. procedure get_final_asmlists(out reslist, datalist: tasmlist);
  90. end;
  91. tasmlisttypedconstbuilderclass = class of tasmlisttypedconstbuilder;
  92. tnodetreetypedconstbuilder = class(ttypedconstbuilder)
  93. protected
  94. resultblock: tblocknode;
  95. statmnt: tstatementnode;
  96. { when parsing a record, the base nade becomes a loadnode of the record,
  97. etc. }
  98. basenode: tnode;
  99. procedure parse_arraydef(def:tarraydef);override;
  100. procedure parse_procvardef(def:tprocvardef);override;
  101. procedure parse_recorddef(def:trecorddef);override;
  102. procedure parse_objectdef(def:tobjectdef);override;
  103. procedure tc_emit_orddef(def: torddef; var node: tnode);override;
  104. procedure tc_emit_floatdef(def: tfloatdef; var node: tnode); override;
  105. procedure tc_emit_classrefdef(def: tclassrefdef; var node: tnode);override;
  106. procedure tc_emit_pointerdef(def: tpointerdef; var node: tnode);override;
  107. procedure tc_emit_setdef(def: tsetdef; var node: tnode);override;
  108. procedure tc_emit_enumdef(def: tenumdef; var node: tnode);override;
  109. procedure tc_emit_stringdef(def: tstringdef; var node: tnode);override;
  110. public
  111. constructor create(sym: tstaticvarsym; previnit: tnode);virtual;
  112. destructor destroy;override;
  113. function parse_into_nodetree: tnode;
  114. end;
  115. tnodetreetypedconstbuilderclass = class of tnodetreetypedconstbuilder;
  116. var
  117. ctypedconstbuilder: ttypedconstbuilderclass;
  118. implementation
  119. uses
  120. SysUtils,
  121. systems,tokens,verbose,
  122. cutils,globals,widestr,scanner,
  123. symtable,
  124. aasmcpu,defutil,defcmp,
  125. { pass 1 }
  126. htypechk,procinfo,
  127. nmat,nadd,ncal,nmem,nset,ncnv,ninl,ncon,nld,nflw,
  128. { parser specific stuff }
  129. pbase,pexpr,pdecvar,
  130. { codegen }
  131. cpuinfo,cgbase,dbgbase,
  132. wpobase
  133. ;
  134. {$maxfpuregisters 0}
  135. function get_next_varsym(def: tabstractrecorddef; const SymList:TFPHashObjectList; var symidx:longint):tsym;inline;
  136. begin
  137. while symidx<SymList.Count do
  138. begin
  139. result:=tsym(def.symtable.SymList[symidx]);
  140. inc(symidx);
  141. if (result.typ=fieldvarsym) and
  142. not(sp_static in result.symoptions) then
  143. exit;
  144. end;
  145. result:=nil;
  146. end;
  147. {*****************************************************************************
  148. read typed const
  149. *****************************************************************************}
  150. procedure ttypedconstbuilder.parse_orddef(def:torddef);
  151. var
  152. n : tnode;
  153. begin
  154. n:=comp_expr([ef_accept_equal]);
  155. { for C-style booleans, true=-1 and false=0) }
  156. if is_cbool(def) then
  157. inserttypeconv(n,def);
  158. tc_emit_orddef(def,n);
  159. n.free;
  160. end;
  161. procedure ttypedconstbuilder.parse_floatdef(def:tfloatdef);
  162. var
  163. n : tnode;
  164. begin
  165. n:=comp_expr([ef_accept_equal]);
  166. tc_emit_floatdef(def,n);
  167. n.free;
  168. end;
  169. procedure ttypedconstbuilder.parse_classrefdef(def:tclassrefdef);
  170. var
  171. n : tnode;
  172. begin
  173. n:=comp_expr([ef_accept_equal]);
  174. case n.nodetype of
  175. loadvmtaddrn:
  176. begin
  177. { update wpo info }
  178. if not assigned(current_procinfo) or
  179. (po_inline in current_procinfo.procdef.procoptions) or
  180. wpoinfomanager.symbol_live(current_procinfo.procdef.mangledname) then
  181. tobjectdef(tclassrefdef(n.resultdef).pointeddef).register_maybe_created_object_type;
  182. end;
  183. end;
  184. tc_emit_classrefdef(def,n);
  185. n.free;
  186. end;
  187. procedure ttypedconstbuilder.parse_pointerdef(def:tpointerdef);
  188. var
  189. p: tnode;
  190. begin
  191. p:=comp_expr([ef_accept_equal]);
  192. tc_emit_pointerdef(def,p);
  193. p.free;
  194. end;
  195. procedure ttypedconstbuilder.parse_setdef(def:tsetdef);
  196. var
  197. p : tnode;
  198. begin
  199. p:=comp_expr([ef_accept_equal]);
  200. tc_emit_setdef(def,p);
  201. p.free;
  202. end;
  203. procedure ttypedconstbuilder.parse_enumdef(def:tenumdef);
  204. var
  205. p : tnode;
  206. begin
  207. p:=comp_expr([ef_accept_equal]);
  208. tc_emit_enumdef(def,p);
  209. p.free;
  210. end;
  211. procedure ttypedconstbuilder.parse_stringdef(def:tstringdef);
  212. var
  213. n : tnode;
  214. begin
  215. n:=comp_expr([ef_accept_equal]);
  216. tc_emit_stringdef(def,n);
  217. n.free;
  218. end;
  219. { ttypedconstbuilder }
  220. procedure ttypedconstbuilder.read_typed_const_data(def:tdef);
  221. var
  222. prev_old_block_type,
  223. old_block_type: tblock_type;
  224. begin
  225. old_block_type:=block_type;
  226. prev_old_block_type:=current_old_block_type;
  227. current_old_block_type:=old_block_type;
  228. block_type:=bt_const;
  229. case def.typ of
  230. orddef :
  231. parse_orddef(torddef(def));
  232. floatdef :
  233. parse_floatdef(tfloatdef(def));
  234. classrefdef :
  235. parse_classrefdef(tclassrefdef(def));
  236. pointerdef :
  237. parse_pointerdef(tpointerdef(def));
  238. setdef :
  239. parse_setdef(tsetdef(def));
  240. enumdef :
  241. parse_enumdef(tenumdef(def));
  242. stringdef :
  243. parse_stringdef(tstringdef(def));
  244. arraydef :
  245. parse_arraydef(tarraydef(def));
  246. procvardef:
  247. parse_procvardef(tprocvardef(def));
  248. recorddef:
  249. parse_recorddef(trecorddef(def));
  250. objectdef:
  251. parse_objectdef(tobjectdef(def));
  252. errordef:
  253. begin
  254. { try to consume something useful }
  255. if token=_LKLAMMER then
  256. consume_all_until(_RKLAMMER)
  257. else
  258. consume_all_until(_SEMICOLON);
  259. end;
  260. else
  261. Message(parser_e_type_const_not_possible);
  262. end;
  263. block_type:=old_block_type;
  264. current_old_block_type:=prev_old_block_type;
  265. end;
  266. constructor ttypedconstbuilder.create(sym: tstaticvarsym);
  267. begin
  268. tcsym:=sym;
  269. end;
  270. {*****************************************************************************
  271. Bitpacked value helpers
  272. *****************************************************************************}
  273. procedure initbitpackval(out bp: tbitpackedval; packedbitsize: byte);
  274. begin
  275. bp.curval:=0;
  276. bp.nextval:=0;
  277. bp.curbitoffset:=0;
  278. bp.packedbitsize:=packedbitsize;
  279. bp.loadbitsize:=packedbitsloadsize(bp.packedbitsize)*8;
  280. end;
  281. {$push}
  282. {$r-}
  283. {$q-}
  284. { (values between quotes below refer to fields of bp; fields not }
  285. { mentioned are unused by this routine) }
  286. { bitpacks "value" as bitpacked value of bitsize "packedbitsize" into }
  287. { "curval", which has already been filled up to "curbitoffset", and }
  288. { stores the spillover if any into "nextval". It also updates }
  289. { curbitoffset to reflect how many bits of currval are now used (can be }
  290. { > AIntBits in case of spillover) }
  291. procedure bitpackval(value: aword; var bp: tbitpackedval);
  292. var
  293. shiftcount: longint;
  294. begin
  295. if (target_info.endian=endian_big) then
  296. begin
  297. { bitpacked format: left-aligned (i.e., "big endian bitness") }
  298. bp.curval:=bp.curval or ((value shl (AIntBits-bp.packedbitsize)) shr bp.curbitoffset);
  299. shiftcount:=((AIntBits-bp.packedbitsize)-bp.curbitoffset);
  300. { carry-over to the next element? }
  301. if (shiftcount<0) then
  302. bp.nextval:=(value and ((aword(1) shl (-shiftcount))-1)) shl
  303. (AIntBits+shiftcount)
  304. end
  305. else
  306. begin
  307. { bitpacked format: right aligned (i.e., "little endian bitness") }
  308. bp.curval:=bp.curval or (value shl bp.curbitoffset);
  309. { carry-over to the next element? }
  310. if (bp.curbitoffset+bp.packedbitsize>AIntBits) then
  311. bp.nextval:=value shr (AIntBits-bp.curbitoffset)
  312. end;
  313. inc(bp.curbitoffset,bp.packedbitsize);
  314. end;
  315. procedure tasmlisttypedconstbuilder.flush_packed_value(var bp: tbitpackedval);
  316. var
  317. bitstowrite: longint;
  318. writeval : AInt;
  319. begin
  320. if (bp.curbitoffset < AIntBits) then
  321. begin
  322. { forced flush -> write multiple of loadsize }
  323. bitstowrite:=align(bp.curbitoffset,bp.loadbitsize);
  324. bp.curbitoffset:=0;
  325. end
  326. else
  327. begin
  328. bitstowrite:=AIntBits;
  329. dec(bp.curbitoffset,AIntBits);
  330. end;
  331. while (bitstowrite>=bp.loadbitsize) do
  332. begin
  333. if (target_info.endian=endian_little) then
  334. begin
  335. { write lowest "loadbitsize" bits }
  336. writeval:=bp.curval and (aint(-1) shr ((sizeof(aint)*8)-bp.loadbitsize));
  337. bp.curval:=bp.curval shr bp.loadbitsize;
  338. end
  339. else
  340. begin
  341. { write highest "loadbitsize" bits }
  342. writeval:=bp.curval shr (AIntBits-bp.loadbitsize);
  343. bp.curval:=bp.curval shl bp.loadbitsize;
  344. end;
  345. case bp.loadbitsize of
  346. 8: ftcb.emit_tai(tai_const.create_8bit(writeval),u8inttype);
  347. 16: ftcb.emit_tai(tai_const.create_16bit(writeval),u16inttype);
  348. 32: ftcb.emit_tai(tai_const.create_32bit(writeval),u32inttype);
  349. 64: ftcb.emit_tai(tai_const.create_64bit(writeval),u64inttype);
  350. else
  351. internalerror(2013111101);
  352. end;
  353. dec(bitstowrite,bp.loadbitsize);
  354. end;
  355. bp.curval:=bp.nextval;
  356. bp.nextval:=0;
  357. end;
  358. {$pop}
  359. { parses a packed array constant }
  360. procedure tasmlisttypedconstbuilder.parse_packed_array_def(def: tarraydef);
  361. var
  362. i : aint;
  363. bp : tbitpackedval;
  364. begin
  365. if not(def.elementdef.typ in [orddef,enumdef]) then
  366. internalerror(2007022010);
  367. ftcb.maybe_begin_aggregate(def);
  368. { begin of the array }
  369. consume(_LKLAMMER);
  370. initbitpackval(bp,def.elepackedbitsize);
  371. i:=def.lowrange;
  372. { can't use for-loop, fails when cross-compiling from }
  373. { 32 to 64 bit because i is then 64 bit }
  374. while (i<def.highrange) do
  375. begin
  376. { get next item of the packed array }
  377. if not parse_single_packed_const(def.elementdef,bp) then
  378. exit;
  379. consume(_COMMA);
  380. inc(i);
  381. end;
  382. { final item }
  383. if not parse_single_packed_const(def.elementdef,bp) then
  384. exit;
  385. { flush final incomplete value if necessary }
  386. if (bp.curbitoffset <> 0) then
  387. flush_packed_value(bp);
  388. ftcb.maybe_end_aggregate(def);
  389. consume(_RKLAMMER);
  390. end;
  391. constructor tasmlisttypedconstbuilder.create(sym: tstaticvarsym);
  392. begin
  393. inherited;
  394. fsym:=sym;
  395. ftcb:=ctai_typedconstbuilder.create([tcalo_make_dead_strippable]);
  396. fdatalist:=tasmlist.create;
  397. curoffset:=0;
  398. end;
  399. destructor tasmlisttypedconstbuilder.Destroy;
  400. begin
  401. fdatalist.free;
  402. ftcb.free;
  403. inherited Destroy;
  404. end;
  405. procedure tasmlisttypedconstbuilder.tc_emit_stringdef(def: tstringdef; var node: tnode);
  406. var
  407. strlength : aint;
  408. strval : pchar;
  409. ll : tasmlabofs;
  410. ca : pchar;
  411. winlike : boolean;
  412. hsym : tconstsym;
  413. begin
  414. strval:='';
  415. { load strval and strlength of the constant tree }
  416. if (node.nodetype=stringconstn) or is_wide_or_unicode_string(def) or is_constwidecharnode(node) or
  417. ((node.nodetype=typen) and is_interfacecorba(ttypenode(node).typedef)) or
  418. is_constcharnode(node) then
  419. begin
  420. { convert to the expected string type so that
  421. for widestrings strval is a pcompilerwidestring }
  422. inserttypeconv(node,def);
  423. if (not codegenerror) and
  424. (node.nodetype=stringconstn) then
  425. begin
  426. strlength:=tstringconstnode(node).len;
  427. strval:=tstringconstnode(node).value_str;
  428. { the def may have changed from e.g. RawByteString to
  429. AnsiString(CP_ACP) }
  430. if node.resultdef.typ=stringdef then
  431. def:=tstringdef(node.resultdef)
  432. else
  433. internalerror(2014010501);
  434. end
  435. else
  436. begin
  437. { an error occurred trying to convert the result to a string }
  438. strlength:=-1;
  439. { it's possible that the type conversion could not be
  440. evaluated at compile-time }
  441. if not codegenerror then
  442. CGMessage(parser_e_widestring_to_ansi_compile_time);
  443. end;
  444. end
  445. else if is_constresourcestringnode(node) then
  446. begin
  447. hsym:=tconstsym(tloadnode(node).symtableentry);
  448. strval:=pchar(hsym.value.valueptr);
  449. strlength:=hsym.value.len;
  450. { Delphi-compatible (mis)feature:
  451. Link AnsiString constants to their initializing resourcestring,
  452. enabling them to be (re)translated at runtime.
  453. Wide/UnicodeString are currently rejected above (with incorrect error message).
  454. ShortStrings cannot be handled unless another table is built for them;
  455. considering this acceptable, because Delphi rejects them altogether.
  456. }
  457. if (not is_shortstring(def)) and
  458. ((tcsym.owner.symtablelevel<=main_program_level) or
  459. (current_old_block_type=bt_const)) then
  460. begin
  461. current_asmdata.ResStrInits.Concat(
  462. TTCInitItem.Create(tcsym,curoffset,
  463. current_asmdata.RefAsmSymbol(make_mangledname('RESSTR',hsym.owner,hsym.name),AT_DATA))
  464. );
  465. Include(tcsym.varoptions,vo_force_finalize);
  466. end;
  467. end
  468. else
  469. begin
  470. Message(parser_e_illegal_expression);
  471. strlength:=-1;
  472. end;
  473. if strlength>=0 then
  474. begin
  475. case def.stringtype of
  476. st_shortstring:
  477. begin
  478. ftcb.maybe_begin_aggregate(def);
  479. if strlength>=def.size then
  480. begin
  481. message2(parser_w_string_too_long,strpas(strval),tostr(def.size-1));
  482. strlength:=def.size-1;
  483. end;
  484. ftcb.emit_tai(Tai_const.Create_8bit(strlength),cansichartype);
  485. { room for the string data + terminating #0 }
  486. getmem(ca,def.size);
  487. move(strval^,ca^,strlength);
  488. { zero-terminate and fill with spaces if size is shorter }
  489. fillchar(ca[strlength],def.size-strlength-1,' ');
  490. ca[strlength]:=#0;
  491. ca[def.size-1]:=#0;
  492. ftcb.emit_tai(Tai_string.Create_pchar(ca,def.size-1),carraydef.getreusable(cansichartype,def.size-1));
  493. ftcb.maybe_end_aggregate(def);
  494. end;
  495. st_ansistring:
  496. begin
  497. { an empty ansi string is nil! }
  498. if (strlength=0) then
  499. begin
  500. ll.lab:=nil;
  501. ll.ofs:=0;
  502. end
  503. else
  504. ll:=ftcb.emit_ansistring_const(fdatalist,strval,strlength,def.encoding);
  505. ftcb.emit_string_offset(ll,strlength,def.stringtype,false,charpointertype);
  506. end;
  507. st_unicodestring,
  508. st_widestring:
  509. begin
  510. { an empty wide/unicode string is nil! }
  511. if (strlength=0) then
  512. begin
  513. ll.lab:=nil;
  514. ll.ofs:=0;
  515. winlike:=false;
  516. end
  517. else
  518. begin
  519. winlike:=(def.stringtype=st_widestring) and (tf_winlikewidestring in target_info.flags);
  520. ll:=ftcb.emit_unicodestring_const(fdatalist,
  521. strval,
  522. def.encoding,
  523. winlike);
  524. { Collect Windows widestrings that need initialization at startup.
  525. Local initialized vars are excluded because they are initialized
  526. at function entry instead. }
  527. if winlike and
  528. ((tcsym.owner.symtablelevel<=main_program_level) or
  529. (current_old_block_type=bt_const)) then
  530. begin
  531. if ll.ofs<>0 then
  532. internalerror(2012051704);
  533. current_asmdata.WideInits.Concat(
  534. TTCInitItem.Create(tcsym,curoffset,ll.lab)
  535. );
  536. ll.lab:=nil;
  537. ll.ofs:=0;
  538. Include(tcsym.varoptions,vo_force_finalize);
  539. end;
  540. end;
  541. ftcb.emit_string_offset(ll,strlength,def.stringtype,winlike,widecharpointertype);
  542. end;
  543. else
  544. internalerror(200107081);
  545. end;
  546. end;
  547. end;
  548. procedure tasmlisttypedconstbuilder.tc_emit_orddef(def: torddef; var node: tnode);
  549. var
  550. intvalue: tconstexprint;
  551. procedure do_error;
  552. begin
  553. if is_constnode(node) then
  554. IncompatibleTypes(node.resultdef, def)
  555. else if not(parse_generic) then
  556. Message(parser_e_illegal_expression);
  557. end;
  558. begin
  559. case def.ordtype of
  560. pasbool8,
  561. bool8bit,
  562. pasbool16,
  563. bool16bit,
  564. pasbool32,
  565. bool32bit,
  566. pasbool64,
  567. bool64bit:
  568. begin
  569. if is_constboolnode(node) then
  570. begin
  571. testrange(def,tordconstnode(node).value,false,false);
  572. ftcb.emit_ord_const(tordconstnode(node).value.svalue,def)
  573. end
  574. else
  575. do_error;
  576. end;
  577. uchar :
  578. begin
  579. if is_constwidecharnode(node) then
  580. inserttypeconv(node,cansichartype);
  581. if is_constcharnode(node) or
  582. ((m_delphi in current_settings.modeswitches) and
  583. is_constwidecharnode(node) and
  584. (tordconstnode(node).value <= 255)) then
  585. ftcb.emit_ord_const(byte(tordconstnode(node).value.svalue),def)
  586. else
  587. do_error;
  588. end;
  589. uwidechar :
  590. begin
  591. if is_constcharnode(node) then
  592. inserttypeconv(node,cwidechartype);
  593. if is_constwidecharnode(node) then
  594. ftcb.emit_ord_const(word(tordconstnode(node).value.svalue),def)
  595. else
  596. do_error;
  597. end;
  598. s8bit,u8bit,
  599. u16bit,s16bit,
  600. s32bit,u32bit,
  601. s64bit,u64bit :
  602. begin
  603. if is_constintnode(node) then
  604. begin
  605. testrange(def,tordconstnode(node).value,false,false);
  606. ftcb.emit_ord_const(tordconstnode(node).value.svalue,def);
  607. end
  608. else
  609. do_error;
  610. end;
  611. scurrency:
  612. begin
  613. if is_constintnode(node) then
  614. intvalue:=tordconstnode(node).value*10000
  615. { allow bootstrapping }
  616. else if is_constrealnode(node) then
  617. intvalue:=PInt64(@trealconstnode(node).value_currency)^
  618. else
  619. begin
  620. intvalue:=0;
  621. IncompatibleTypes(node.resultdef, def);
  622. end;
  623. ftcb.emit_ord_const(intvalue,def);
  624. end;
  625. else
  626. internalerror(200611052);
  627. end;
  628. end;
  629. procedure tasmlisttypedconstbuilder.tc_emit_floatdef(def: tfloatdef; var node: tnode);
  630. var
  631. value : bestreal;
  632. begin
  633. value:=0.0;
  634. if is_constrealnode(node) then
  635. value:=trealconstnode(node).value_real
  636. else if is_constintnode(node) then
  637. value:=tordconstnode(node).value
  638. else if is_constnode(node) then
  639. IncompatibleTypes(node.resultdef, def)
  640. else
  641. Message(parser_e_illegal_expression);
  642. case def.floattype of
  643. s32real :
  644. ftcb.emit_tai(tai_realconst.create_s32real(ts32real(value)),def);
  645. s64real :
  646. {$ifdef ARM}
  647. if is_double_hilo_swapped then
  648. ftcb.emit_tai(tai_realconst.create_s64real_hiloswapped(ts64real(value)),def)
  649. else
  650. {$endif ARM}
  651. ftcb.emit_tai(tai_realconst.create_s64real(ts64real(value)),def);
  652. s80real :
  653. ftcb.emit_tai(tai_realconst.create_s80real(value,s80floattype.size),def);
  654. sc80real :
  655. ftcb.emit_tai(tai_realconst.create_s80real(value,sc80floattype.size),def);
  656. s64comp :
  657. { the round is necessary for native compilers where comp isn't a float }
  658. ftcb.emit_tai(tai_realconst.create_s64compreal(round(value)),def);
  659. s64currency:
  660. ftcb.emit_tai(tai_realconst.create_s64compreal(round(value*10000)),def);
  661. s128real:
  662. ftcb.emit_tai(tai_realconst.create_s128real(value),def);
  663. else
  664. internalerror(200611053);
  665. end;
  666. end;
  667. procedure tasmlisttypedconstbuilder.tc_emit_classrefdef(def: tclassrefdef; var node: tnode);
  668. begin
  669. case node.nodetype of
  670. loadvmtaddrn:
  671. begin
  672. if not def_is_related(tobjectdef(tclassrefdef(node.resultdef).pointeddef),tobjectdef(def.pointeddef)) then
  673. IncompatibleTypes(node.resultdef, def);
  674. ftcb.emit_tai(Tai_const.Create_sym(current_asmdata.RefAsmSymbol(Tobjectdef(tclassrefdef(node.resultdef).pointeddef).vmt_mangledname,AT_DATA)),def);
  675. end;
  676. niln:
  677. ftcb.emit_tai(Tai_const.Create_sym(nil),def);
  678. else if is_constnode(node) then
  679. IncompatibleTypes(node.resultdef, def)
  680. else
  681. Message(parser_e_illegal_expression);
  682. end;
  683. end;
  684. procedure tasmlisttypedconstbuilder.tc_emit_pointerdef(def: tpointerdef; var node: tnode);
  685. var
  686. hp : tnode;
  687. srsym : tsym;
  688. pd : tprocdef;
  689. ca : pchar;
  690. pw : pcompilerwidestring;
  691. i,len : longint;
  692. ll : tasmlabel;
  693. varalign : shortint;
  694. datadef : tdef;
  695. datatcb : ttai_typedconstbuilder;
  696. begin
  697. { remove equal typecasts for pointer/nil addresses }
  698. if (node.nodetype=typeconvn) then
  699. with Ttypeconvnode(node) do
  700. if (left.nodetype in [addrn,niln]) and equal_defs(def,node.resultdef) then
  701. begin
  702. hp:=left;
  703. left:=nil;
  704. node.free;
  705. node:=hp;
  706. end;
  707. { allows horrible ofs(typeof(TButton)^) code !! }
  708. if (node.nodetype=typeconvn) then
  709. with Ttypeconvnode(node) do
  710. if (left.nodetype=addrn) and equal_defs(uinttype,node.resultdef) then
  711. begin
  712. hp:=left;
  713. left:=nil;
  714. node.free;
  715. node:=hp;
  716. end;
  717. if (node.nodetype=addrn) then
  718. with Taddrnode(node) do
  719. if left.nodetype=derefn then
  720. begin
  721. hp:=tderefnode(left).left;
  722. tderefnode(left).left:=nil;
  723. node.free;
  724. node:=hp;
  725. end;
  726. { const pointer ? }
  727. if (node.nodetype = pointerconstn) then
  728. begin
  729. ftcb.queue_init(def);
  730. ftcb.queue_typeconvn(ptrsinttype,def);
  731. {$if sizeof(TConstPtrUInt)=8}
  732. ftcb.queue_emit_ordconst(int64(tpointerconstnode(node).value),ptrsinttype);
  733. {$else}
  734. {$if sizeof(TConstPtrUInt)=4}
  735. ftcb.queue_emit_ordconst(longint(tpointerconstnode(node).value),ptrsinttype);
  736. {$else}
  737. {$if sizeof(TConstPtrUInt)=2}
  738. ftcb.queue_emit_ordconst(smallint(tpointerconstnode(node).value),ptrsinttype);
  739. {$else}
  740. {$if sizeof(TConstPtrUInt)=1}
  741. ftcb.queue_emit_ordconst(shortint(tpointerconstnode(node).value),ptrsinttype);
  742. {$else}
  743. internalerror(200404122);
  744. {$endif} {$endif} {$endif} {$endif}
  745. end
  746. { nil pointer ? }
  747. else if node.nodetype=niln then
  748. ftcb.emit_tai(Tai_const.Create_sym(nil),def)
  749. { maybe pchar ? }
  750. else
  751. if is_char(def.pointeddef) and
  752. (node.nodetype<>addrn) then
  753. begin
  754. { create a tcb for the string data (it's placed in a separate
  755. asmlist) }
  756. ftcb.start_internal_data_builder(fdatalist,sec_rodata,'',datatcb,ll);
  757. if node.nodetype=stringconstn then
  758. varalign:=size_2_align(tstringconstnode(node).len)
  759. else
  760. varalign:=1;
  761. varalign:=const_align(varalign);
  762. { represent the string data as an array }
  763. if node.nodetype=stringconstn then
  764. begin
  765. len:=tstringconstnode(node).len;
  766. { For tp7 the maximum lentgh can be 255 }
  767. if (m_tp7 in current_settings.modeswitches) and
  768. (len>255) then
  769. len:=255;
  770. getmem(ca,len+1);
  771. move(tstringconstnode(node).value_str^,ca^,len+1);
  772. datadef:=carraydef.getreusable(cansichartype,len+1);
  773. datatcb.maybe_begin_aggregate(datadef);
  774. datatcb.emit_tai(Tai_string.Create_pchar(ca,len+1),datadef);
  775. datatcb.maybe_end_aggregate(datadef);
  776. end
  777. else if is_constcharnode(node) then
  778. begin
  779. datadef:=carraydef.getreusable(cansichartype,2);
  780. datatcb.maybe_begin_aggregate(datadef);
  781. datatcb.emit_tai(Tai_string.Create(char(byte(tordconstnode(node).value.svalue))+#0),datadef);
  782. datatcb.maybe_end_aggregate(datadef);
  783. end
  784. else
  785. begin
  786. IncompatibleTypes(node.resultdef, def);
  787. datadef:=carraydef.getreusable(cansichartype,1);
  788. end;
  789. ftcb.finish_internal_data_builder(datatcb,ll,datadef,varalign);
  790. { we now emit the address of the first element of the array
  791. containing the string data }
  792. ftcb.queue_init(def);
  793. { the first element ... }
  794. ftcb.queue_vecn(datadef,0);
  795. { ... of the string array }
  796. ftcb.queue_emit_asmsym(ll,datadef);
  797. end
  798. { maybe pwidechar ? }
  799. else
  800. if is_widechar(def.pointeddef) and
  801. (node.nodetype<>addrn) then
  802. begin
  803. if (node.nodetype in [stringconstn,ordconstn]) then
  804. begin
  805. { convert to unicodestring stringconstn }
  806. inserttypeconv(node,cunicodestringtype);
  807. if (node.nodetype=stringconstn) and
  808. (tstringconstnode(node).cst_type in [cst_widestring,cst_unicodestring]) then
  809. begin
  810. { create a tcb for the string data (it's placed in a separate
  811. asmlist) }
  812. ftcb.start_internal_data_builder(fdatalist,sec_rodata,'',datatcb,ll);
  813. datatcb:=ctai_typedconstbuilder.create([tcalo_is_lab,tcalo_make_dead_strippable]);
  814. pw:=pcompilerwidestring(tstringconstnode(node).value_str);
  815. { include terminating #0 }
  816. datadef:=carraydef.getreusable(cwidechartype,tstringconstnode(node).len+1);
  817. datatcb.maybe_begin_aggregate(datadef);
  818. for i:=0 to tstringconstnode(node).len-1 do
  819. datatcb.emit_tai(Tai_const.Create_16bit(pw^.data[i]),cwidechartype);
  820. { ending #0 }
  821. datatcb.emit_tai(Tai_const.Create_16bit(0),cwidechartype);
  822. datatcb.maybe_end_aggregate(datadef);
  823. { concat add the string data to the fdatalist }
  824. ftcb.finish_internal_data_builder(datatcb,ll,datadef,const_align(sizeof(pint)));
  825. { we now emit the address of the first element of the array
  826. containing the string data }
  827. ftcb.queue_init(def);
  828. { the first element ... }
  829. ftcb.queue_vecn(datadef,0);
  830. { ... of the string array }
  831. ftcb.queue_emit_asmsym(ll,datadef);
  832. end;
  833. end
  834. else
  835. IncompatibleTypes(node.resultdef, def);
  836. end
  837. else
  838. if (node.nodetype=addrn) or
  839. is_proc2procvar_load(node,pd) then
  840. begin
  841. { insert typeconv }
  842. inserttypeconv(node,def);
  843. hp:=node;
  844. while assigned(hp) and (hp.nodetype in [addrn,typeconvn,subscriptn,vecn]) do
  845. hp:=tunarynode(hp).left;
  846. if (hp.nodetype=loadn) then
  847. begin
  848. hp:=node;
  849. ftcb.queue_init(def);
  850. while assigned(hp) and (hp.nodetype<>loadn) do
  851. begin
  852. case hp.nodetype of
  853. vecn :
  854. begin
  855. if is_constintnode(tvecnode(hp).right) and
  856. not is_ansistring(tvecnode(hp).left.resultdef) and
  857. not is_wide_or_unicode_string(tvecnode(hp).left.resultdef) then
  858. ftcb.queue_vecn(tvecnode(hp).left.resultdef,get_ordinal_value(tvecnode(hp).right))
  859. else
  860. Message(parser_e_illegal_expression);
  861. end;
  862. subscriptn :
  863. ftcb.queue_subscriptn(tabstractrecorddef(tsubscriptnode(hp).left.resultdef),tsubscriptnode(hp).vs);
  864. typeconvn :
  865. begin
  866. if not(ttypeconvnode(hp).convtype in [tc_equal,tc_proc_2_procvar]) then
  867. Message(parser_e_illegal_expression)
  868. else
  869. ftcb.queue_typeconvn(ttypeconvnode(hp).left.resultdef,hp.resultdef);
  870. end;
  871. addrn :
  872. { nothing, is implicit };
  873. else
  874. Message(parser_e_illegal_expression);
  875. end;
  876. hp:=tunarynode(hp).left;
  877. end;
  878. srsym:=tloadnode(hp).symtableentry;
  879. case srsym.typ of
  880. procsym :
  881. begin
  882. pd:=tprocdef(tprocsym(srsym).ProcdefList[0]);
  883. if Tprocsym(srsym).ProcdefList.Count>1 then
  884. Message(parser_e_no_overloaded_procvars);
  885. if po_abstractmethod in pd.procoptions then
  886. Message(type_e_cant_take_address_of_abstract_method)
  887. else
  888. ftcb.queue_emit_proc(pd);
  889. end;
  890. staticvarsym :
  891. ftcb.queue_emit_staticvar(tstaticvarsym(srsym));
  892. labelsym :
  893. ftcb.queue_emit_label(tlabelsym(srsym));
  894. constsym :
  895. if tconstsym(srsym).consttyp=constresourcestring then
  896. ftcb.queue_emit_const(tconstsym(srsym))
  897. else
  898. Message(type_e_variable_id_expected);
  899. else
  900. Message(type_e_variable_id_expected);
  901. end;
  902. end
  903. else
  904. Message(parser_e_illegal_expression);
  905. end
  906. else
  907. { allow typeof(Object type)}
  908. if (node.nodetype=inlinen) and
  909. (tinlinenode(node).inlinenumber=in_typeof_x) then
  910. begin
  911. if (tinlinenode(node).left.nodetype=typen) then
  912. begin
  913. // TODO correct type?
  914. ftcb.emit_tai(Tai_const.createname(
  915. tobjectdef(tinlinenode(node).left.resultdef).vmt_mangledname,AT_DATA,0),
  916. voidpointertype);
  917. end
  918. else
  919. Message(parser_e_illegal_expression);
  920. end
  921. else
  922. Message(parser_e_illegal_expression);
  923. end;
  924. procedure tasmlisttypedconstbuilder.tc_emit_setdef(def: tsetdef; var node: tnode);
  925. type
  926. setbytes = array[0..31] of byte;
  927. Psetbytes = ^setbytes;
  928. var
  929. i: longint;
  930. begin
  931. if node.nodetype=setconstn then
  932. begin
  933. { be sure to convert to the correct result, else
  934. it can generate smallset data instead of normalset (PFV) }
  935. inserttypeconv(node,def);
  936. { we only allow const sets }
  937. if (node.nodetype<>setconstn) or
  938. assigned(tsetconstnode(node).left) then
  939. Message(parser_e_illegal_expression)
  940. else
  941. begin
  942. ftcb.maybe_begin_aggregate(def);
  943. tsetconstnode(node).adjustforsetbase;
  944. { this writing is endian-dependant }
  945. if source_info.endian = target_info.endian then
  946. begin
  947. for i:=0 to node.resultdef.size-1 do
  948. ftcb.emit_tai(tai_const.create_8bit(Psetbytes(tsetconstnode(node).value_set)^[i]),u8inttype);
  949. end
  950. else
  951. begin
  952. for i:=0 to node.resultdef.size-1 do
  953. ftcb.emit_tai(tai_const.create_8bit(reverse_byte(Psetbytes(tsetconstnode(node).value_set)^[i])),u8inttype);
  954. end;
  955. ftcb.maybe_end_aggregate(def);
  956. end;
  957. end
  958. else
  959. Message(parser_e_illegal_expression);
  960. end;
  961. procedure tasmlisttypedconstbuilder.tc_emit_enumdef(def: tenumdef; var node: tnode);
  962. begin
  963. if node.nodetype=ordconstn then
  964. begin
  965. if equal_defs(node.resultdef,def) or
  966. is_subequal(node.resultdef,def) then
  967. begin
  968. testrange(def,tordconstnode(node).value,false,false);
  969. case longint(node.resultdef.size) of
  970. 1 : ftcb.emit_tai(Tai_const.Create_8bit(Byte(tordconstnode(node).value.svalue)),def);
  971. 2 : ftcb.emit_tai(Tai_const.Create_16bit(Word(tordconstnode(node).value.svalue)),def);
  972. 4 : ftcb.emit_tai(Tai_const.Create_32bit(Longint(tordconstnode(node).value.svalue)),def);
  973. end;
  974. end
  975. else
  976. IncompatibleTypes(node.resultdef,def);
  977. end
  978. else
  979. Message(parser_e_illegal_expression);
  980. end;
  981. { parse a single constant and add it to the packed const info }
  982. { represented by curval etc (see explanation of bitpackval for }
  983. { what the different parameters mean) }
  984. function tasmlisttypedconstbuilder.parse_single_packed_const(def: tdef; var bp: tbitpackedval): boolean;
  985. var
  986. node: tnode;
  987. begin
  988. result:=true;
  989. node:=comp_expr([ef_accept_equal]);
  990. if (node.nodetype <> ordconstn) or
  991. (not equal_defs(node.resultdef,def) and
  992. not is_subequal(node.resultdef,def)) then
  993. begin
  994. incompatibletypes(node.resultdef,def);
  995. node.free;
  996. consume_all_until(_SEMICOLON);
  997. result:=false;
  998. exit;
  999. end;
  1000. if (Tordconstnode(node).value<qword(low(Aword))) or (Tordconstnode(node).value>qword(high(Aword))) then
  1001. message3(type_e_range_check_error_bounds,tostr(Tordconstnode(node).value),tostr(low(Aword)),tostr(high(Aword)))
  1002. else
  1003. bitpackval(Tordconstnode(node).value.uvalue,bp);
  1004. if (bp.curbitoffset>=AIntBits) then
  1005. flush_packed_value(bp);
  1006. node.free;
  1007. end;
  1008. procedure tasmlisttypedconstbuilder.get_final_asmlists(out reslist, datalist: tasmlist);
  1009. var
  1010. asmsym: tasmsymbol;
  1011. addstabx: boolean;
  1012. sec: TAsmSectiontype;
  1013. secname: ansistring;
  1014. begin
  1015. addstabx:=false;
  1016. if fsym.globalasmsym then
  1017. begin
  1018. if (target_dbg.id=dbg_stabx) and
  1019. (cs_debuginfo in current_settings.moduleswitches) and
  1020. not assigned(current_asmdata.GetAsmSymbol(fsym.name)) then
  1021. addstabx:=true;
  1022. asmsym:=current_asmdata.DefineAsmSymbol(fsym.mangledname,AB_GLOBAL,AT_DATA)
  1023. end
  1024. else
  1025. asmsym:=current_asmdata.DefineAsmSymbol(fsym.mangledname,AB_LOCAL,AT_DATA);
  1026. if vo_has_section in fsym.varoptions then
  1027. begin
  1028. sec:=sec_user;
  1029. secname:=fsym.section;
  1030. end
  1031. else
  1032. begin
  1033. { Certain types like windows WideString are initialized at runtime and cannot
  1034. be placed into readonly memory }
  1035. if (fsym.varspez=vs_const) and
  1036. not (vo_force_finalize in fsym.varoptions) then
  1037. sec:=sec_rodata
  1038. else
  1039. sec:=sec_data;
  1040. secname:=asmsym.Name;
  1041. end;
  1042. reslist:=ftcb.get_final_asmlist(asmsym,fsym.vardef,sec,secname,fsym.vardef.alignment);
  1043. if addstabx then
  1044. begin
  1045. { see same code in ncgutil.insertbssdata }
  1046. reslist.insert(tai_directive.Create(asd_reference,fsym.name));
  1047. reslist.insert(tai_symbol.Create(current_asmdata.DefineAsmSymbol(fsym.name,AB_LOCAL,AT_DATA),0));
  1048. end;
  1049. datalist:=fdatalist;
  1050. end;
  1051. procedure tasmlisttypedconstbuilder.parse_arraydef(def:tarraydef);
  1052. var
  1053. n : tnode;
  1054. i : longint;
  1055. len : asizeint;
  1056. ch : array[0..1] of char;
  1057. ca : pbyte;
  1058. int_const: tai_const;
  1059. char_size: integer;
  1060. oldoffset: asizeint;
  1061. dummy : byte;
  1062. begin
  1063. { dynamic array nil }
  1064. if is_dynamic_array(def) then
  1065. begin
  1066. { Only allow nil initialization }
  1067. consume(_NIL);
  1068. ftcb.emit_tai(Tai_const.Create_sym(nil),def);
  1069. end
  1070. { packed array constant }
  1071. else if is_packed_array(def) and
  1072. ((def.elepackedbitsize mod 8 <> 0) or
  1073. not ispowerof2(def.elepackedbitsize div 8,i)) then
  1074. begin
  1075. parse_packed_array_def(def);
  1076. end
  1077. { normal array const between brackets }
  1078. else if try_to_consume(_LKLAMMER) then
  1079. begin
  1080. ftcb.maybe_begin_aggregate(def);
  1081. oldoffset:=curoffset;
  1082. curoffset:=0;
  1083. { in case of a generic subroutine, it might be we cannot
  1084. determine the size yet }
  1085. if assigned(current_procinfo) and (df_generic in current_procinfo.procdef.defoptions) then
  1086. begin
  1087. while true do
  1088. begin
  1089. read_typed_const_data(def.elementdef);
  1090. if token=_RKLAMMER then
  1091. begin
  1092. consume(_RKLAMMER);
  1093. break;
  1094. end
  1095. else
  1096. consume(_COMMA);
  1097. end;
  1098. end
  1099. else
  1100. begin
  1101. for i:=def.lowrange to def.highrange-1 do
  1102. begin
  1103. read_typed_const_data(def.elementdef);
  1104. Inc(curoffset,def.elementdef.size);
  1105. if token=_RKLAMMER then
  1106. begin
  1107. Message1(parser_e_more_array_elements_expected,tostr(def.highrange-i));
  1108. consume(_RKLAMMER);
  1109. exit;
  1110. end
  1111. else
  1112. consume(_COMMA);
  1113. end;
  1114. read_typed_const_data(def.elementdef);
  1115. consume(_RKLAMMER);
  1116. end;
  1117. curoffset:=oldoffset;
  1118. ftcb.maybe_end_aggregate(def);
  1119. end
  1120. { if array of char then we allow also a string }
  1121. else if is_anychar(def.elementdef) then
  1122. begin
  1123. ftcb.maybe_begin_aggregate(def);
  1124. char_size:=def.elementdef.size;
  1125. n:=comp_expr([ef_accept_equal]);
  1126. if n.nodetype=stringconstn then
  1127. begin
  1128. len:=tstringconstnode(n).len;
  1129. case char_size of
  1130. 1:
  1131. begin
  1132. if (tstringconstnode(n).cst_type in [cst_unicodestring,cst_widestring]) then
  1133. inserttypeconv(n,getansistringdef);
  1134. if n.nodetype<>stringconstn then
  1135. internalerror(2010033003);
  1136. ca:=pointer(tstringconstnode(n).value_str);
  1137. end;
  1138. 2:
  1139. begin
  1140. inserttypeconv(n,cunicodestringtype);
  1141. if n.nodetype<>stringconstn then
  1142. internalerror(2010033003);
  1143. ca:=pointer(pcompilerwidestring(tstringconstnode(n).value_str)^.data)
  1144. end;
  1145. else
  1146. internalerror(2010033005);
  1147. end;
  1148. { For tp7 the maximum lentgh can be 255 }
  1149. if (m_tp7 in current_settings.modeswitches) and
  1150. (len>255) then
  1151. len:=255;
  1152. end
  1153. else if is_constcharnode(n) then
  1154. begin
  1155. case char_size of
  1156. 1:
  1157. ch[0]:=chr(tordconstnode(n).value.uvalue and $ff);
  1158. 2:
  1159. begin
  1160. inserttypeconv(n,cwidechartype);
  1161. if not is_constwidecharnode(n) then
  1162. internalerror(2010033001);
  1163. widechar(ch):=widechar(tordconstnode(n).value.uvalue and $ffff);
  1164. end;
  1165. else
  1166. internalerror(2010033002);
  1167. end;
  1168. ca:=@ch;
  1169. len:=1;
  1170. end
  1171. else if is_constwidecharnode(n) and (current_settings.sourcecodepage<>CP_UTF8) then
  1172. begin
  1173. case char_size of
  1174. 1:
  1175. begin
  1176. inserttypeconv(n,cansichartype);
  1177. if not is_constcharnode(n) then
  1178. internalerror(2010033001);
  1179. ch[0]:=chr(tordconstnode(n).value.uvalue and $ff);
  1180. end;
  1181. 2:
  1182. widechar(ch):=widechar(tordconstnode(n).value.uvalue and $ffff);
  1183. else
  1184. internalerror(2010033002);
  1185. end;
  1186. ca:=@ch;
  1187. len:=1;
  1188. end
  1189. else
  1190. begin
  1191. Message(parser_e_illegal_expression);
  1192. len:=0;
  1193. { avoid crash later on }
  1194. dummy:=0;
  1195. ca:=@dummy;
  1196. end;
  1197. if len>(def.highrange-def.lowrange+1) then
  1198. Message(parser_e_string_larger_array);
  1199. for i:=0 to def.highrange-def.lowrange do
  1200. begin
  1201. if i<len then
  1202. begin
  1203. case char_size of
  1204. 1:
  1205. int_const:=Tai_const.Create_char(char_size,pbyte(ca)^);
  1206. 2:
  1207. int_const:=Tai_const.Create_char(char_size,pword(ca)^);
  1208. else
  1209. internalerror(2010033004);
  1210. end;
  1211. inc(ca, char_size);
  1212. end
  1213. else
  1214. {Fill the remaining positions with #0.}
  1215. int_const:=Tai_const.Create_char(char_size,0);
  1216. ftcb.emit_tai(int_const,def.elementdef)
  1217. end;
  1218. ftcb.maybe_end_aggregate(def);
  1219. n.free;
  1220. end
  1221. else
  1222. begin
  1223. { we want the ( }
  1224. consume(_LKLAMMER);
  1225. end;
  1226. end;
  1227. procedure tasmlisttypedconstbuilder.parse_procvardef(def:tprocvardef);
  1228. var
  1229. tmpn,n : tnode;
  1230. pd : tprocdef;
  1231. havepd,
  1232. haveblock: boolean;
  1233. begin
  1234. { Procvars and pointers are no longer compatible. }
  1235. { under tp: =nil or =var under fpc: =nil or =@var }
  1236. if try_to_consume(_NIL) then
  1237. begin
  1238. ftcb.maybe_begin_aggregate(def);
  1239. { we need the procdef type called by the procvar here, not the
  1240. procvar record }
  1241. ftcb.emit_tai_procvar2procdef(Tai_const.Create_sym(nil),def);
  1242. if not def.is_addressonly then
  1243. ftcb.emit_tai(Tai_const.Create_sym(nil),voidpointertype);
  1244. ftcb.maybe_end_aggregate(def);
  1245. exit;
  1246. end;
  1247. { you can't assign a value other than NIL to a typed constant }
  1248. { which is a "procedure of object", because this also requires }
  1249. { address of an object/class instance, which is not known at }
  1250. { compile time (JM) }
  1251. if (po_methodpointer in def.procoptions) then
  1252. Message(parser_e_no_procvarobj_const);
  1253. { parse the rest too, so we can continue with error checking }
  1254. getprocvardef:=def;
  1255. n:=comp_expr([ef_accept_equal]);
  1256. getprocvardef:=nil;
  1257. if codegenerror then
  1258. begin
  1259. n.free;
  1260. exit;
  1261. end;
  1262. { let type conversion check everything needed }
  1263. inserttypeconv(n,def);
  1264. if codegenerror then
  1265. begin
  1266. n.free;
  1267. exit;
  1268. end;
  1269. { in case of a nested procdef initialised with a global routine }
  1270. ftcb.maybe_begin_aggregate(def);
  1271. { to handle type conversions }
  1272. ftcb.queue_init(def);
  1273. { remove typeconvs, that will normally insert a lea
  1274. instruction which is not necessary for us }
  1275. while n.nodetype=typeconvn do
  1276. begin
  1277. ftcb.queue_typeconvn(ttypeconvnode(n).left.resultdef,n.resultdef);
  1278. tmpn:=ttypeconvnode(n).left;
  1279. ttypeconvnode(n).left:=nil;
  1280. n.free;
  1281. n:=tmpn;
  1282. end;
  1283. { remove addrn which we also don't need here }
  1284. if n.nodetype=addrn then
  1285. begin
  1286. tmpn:=taddrnode(n).left;
  1287. taddrnode(n).left:=nil;
  1288. n.free;
  1289. n:=tmpn;
  1290. end;
  1291. pd:=nil;
  1292. { we now need to have a loadn with a procsym }
  1293. havepd:=
  1294. (n.nodetype=loadn) and
  1295. (tloadnode(n).symtableentry.typ=procsym);
  1296. { or a staticvarsym representing a block }
  1297. haveblock:=
  1298. (n.nodetype=loadn) and
  1299. (tloadnode(n).symtableentry.typ=staticvarsym) and
  1300. (sp_internal in tloadnode(n).symtableentry.symoptions);
  1301. if havepd or
  1302. haveblock then
  1303. begin
  1304. if havepd then
  1305. begin
  1306. pd:=tloadnode(n).procdef;
  1307. ftcb.queue_emit_proc(pd);
  1308. end
  1309. else
  1310. begin
  1311. ftcb.queue_emit_staticvar(tstaticvarsym(tloadnode(n).symtableentry));
  1312. end;
  1313. { nested procvar typed consts can only be initialised with nil
  1314. (checked above) or with a global procedure (checked here),
  1315. because in other cases we need a valid frame pointer }
  1316. if is_nested_pd(def) then
  1317. begin
  1318. if haveblock or
  1319. is_nested_pd(pd) then
  1320. Message(parser_e_no_procvarnested_const);
  1321. ftcb.emit_tai(Tai_const.Create_sym(nil),voidpointertype);
  1322. end;
  1323. end
  1324. else if n.nodetype=pointerconstn then
  1325. begin
  1326. ftcb.queue_emit_ordconst(tpointerconstnode(n).value,def);
  1327. if not def.is_addressonly then
  1328. ftcb.emit_tai(Tai_const.Create_sym(nil),voidpointertype);
  1329. end
  1330. else
  1331. Message(parser_e_illegal_expression);
  1332. ftcb.maybe_end_aggregate(def);
  1333. n.free;
  1334. end;
  1335. procedure tasmlisttypedconstbuilder.parse_recorddef(def:trecorddef);
  1336. var
  1337. n : tnode;
  1338. symidx : longint;
  1339. recsym,
  1340. srsym : tsym;
  1341. hs : string;
  1342. sorg,s : TIDString;
  1343. tmpguid : tguid;
  1344. recoffset,
  1345. fillbytes : aint;
  1346. bp : tbitpackedval;
  1347. error,
  1348. is_packed: boolean;
  1349. startoffset: aint;
  1350. procedure handle_stringconstn;
  1351. begin
  1352. hs:=strpas(tstringconstnode(n).value_str);
  1353. if string2guid(hs,tmpguid) then
  1354. ftcb.emit_guid_const(tmpguid)
  1355. else
  1356. Message(parser_e_improper_guid_syntax);
  1357. end;
  1358. var
  1359. i : longint;
  1360. SymList:TFPHashObjectList;
  1361. begin
  1362. { GUID }
  1363. if (def=rec_tguid) and (token=_ID) then
  1364. begin
  1365. n:=comp_expr([ef_accept_equal]);
  1366. if n.nodetype=stringconstn then
  1367. handle_stringconstn
  1368. else
  1369. begin
  1370. inserttypeconv(n,rec_tguid);
  1371. if n.nodetype=guidconstn then
  1372. ftcb.emit_guid_const(tguidconstnode(n).value)
  1373. else
  1374. Message(parser_e_illegal_expression);
  1375. end;
  1376. n.free;
  1377. exit;
  1378. end;
  1379. if (def=rec_tguid) and ((token=_CSTRING) or (token=_CCHAR)) then
  1380. begin
  1381. n:=comp_expr([ef_accept_equal]);
  1382. inserttypeconv(n,cshortstringtype);
  1383. if n.nodetype=stringconstn then
  1384. handle_stringconstn
  1385. else
  1386. Message(parser_e_illegal_expression);
  1387. n.free;
  1388. exit;
  1389. end;
  1390. ftcb.maybe_begin_aggregate(def);
  1391. { bitpacked record? }
  1392. is_packed:=is_packed_record_or_object(def);
  1393. if (is_packed) then
  1394. begin
  1395. { loadbitsize = 8, bitpacked records are always padded to }
  1396. { a multiple of a byte. packedbitsize will be set separately }
  1397. { for each field }
  1398. initbitpackval(bp,0);
  1399. bp.loadbitsize:=8;
  1400. end;
  1401. { normal record }
  1402. consume(_LKLAMMER);
  1403. recoffset:=0;
  1404. sorg:='';
  1405. symidx:=0;
  1406. symlist:=def.symtable.SymList;
  1407. srsym:=get_next_varsym(def,symlist,symidx);
  1408. recsym := nil;
  1409. startoffset:=curoffset;
  1410. while token<>_RKLAMMER do
  1411. begin
  1412. s:=pattern;
  1413. sorg:=orgpattern;
  1414. consume(_ID);
  1415. consume(_COLON);
  1416. error := false;
  1417. recsym := tsym(def.symtable.Find(s));
  1418. if not assigned(recsym) then
  1419. begin
  1420. Message1(sym_e_illegal_field,sorg);
  1421. error := true;
  1422. end;
  1423. if (not error) and
  1424. (not assigned(srsym) or
  1425. (s <> srsym.name)) then
  1426. { possible variant record (JM) }
  1427. begin
  1428. { All parts of a variant start at the same offset }
  1429. { Also allow jumping from one variant part to another, }
  1430. { as long as the offsets match }
  1431. if (assigned(srsym) and
  1432. (tfieldvarsym(recsym).fieldoffset = tfieldvarsym(srsym).fieldoffset)) or
  1433. { srsym is not assigned after parsing w2 in the }
  1434. { typed const in the next example: }
  1435. { type tr = record case byte of }
  1436. { 1: (l1,l2: dword); }
  1437. { 2: (w1,w2: word); }
  1438. { end; }
  1439. { const r: tr = (w1:1;w2:1;l2:5); }
  1440. (tfieldvarsym(recsym).fieldoffset = recoffset) then
  1441. begin
  1442. srsym:=recsym;
  1443. { symidx should contain the next symbol id to search }
  1444. symidx:=SymList.indexof(srsym)+1;
  1445. end
  1446. { going backwards isn't allowed in any mode }
  1447. else if (tfieldvarsym(recsym).fieldoffset<recoffset) then
  1448. begin
  1449. Message(parser_e_invalid_record_const);
  1450. error := true;
  1451. end
  1452. { Delphi allows you to skip fields }
  1453. else if (m_delphi in current_settings.modeswitches) then
  1454. begin
  1455. Message1(parser_w_skipped_fields_before,sorg);
  1456. srsym := recsym;
  1457. end
  1458. { FPC and TP don't }
  1459. else
  1460. begin
  1461. Message1(parser_e_skipped_fields_before,sorg);
  1462. error := true;
  1463. end;
  1464. end;
  1465. if error then
  1466. consume_all_until(_SEMICOLON)
  1467. else
  1468. begin
  1469. { if needed fill (alignment) }
  1470. if tfieldvarsym(srsym).fieldoffset>recoffset then
  1471. begin
  1472. if not(is_packed) then
  1473. fillbytes:=0
  1474. else
  1475. begin
  1476. flush_packed_value(bp);
  1477. { curoffset is now aligned to the next byte }
  1478. recoffset:=align(recoffset,8);
  1479. { offsets are in bits in this case }
  1480. fillbytes:=(tfieldvarsym(srsym).fieldoffset-recoffset) div 8;
  1481. end;
  1482. for i:=1 to fillbytes do
  1483. ftcb.emit_tai(Tai_const.Create_8bit(0),u8inttype)
  1484. end;
  1485. { new position }
  1486. recoffset:=tfieldvarsym(srsym).fieldoffset;
  1487. if not(is_packed) then
  1488. inc(recoffset,tfieldvarsym(srsym).vardef.size)
  1489. else
  1490. inc(recoffset,tfieldvarsym(srsym).vardef.packedbitsize);
  1491. { read the data }
  1492. ftcb.next_field:=tfieldvarsym(srsym);
  1493. if not(is_packed) or
  1494. { only orddefs and enumdefs are bitpacked, as in gcc/gpc }
  1495. not(tfieldvarsym(srsym).vardef.typ in [orddef,enumdef]) then
  1496. begin
  1497. if is_packed then
  1498. begin
  1499. flush_packed_value(bp);
  1500. recoffset:=align(recoffset,8);
  1501. end;
  1502. curoffset:=startoffset+tfieldvarsym(srsym).fieldoffset;
  1503. read_typed_const_data(tfieldvarsym(srsym).vardef);
  1504. end
  1505. else
  1506. begin
  1507. bp.packedbitsize:=tfieldvarsym(srsym).vardef.packedbitsize;
  1508. parse_single_packed_const(tfieldvarsym(srsym).vardef,bp);
  1509. end;
  1510. { keep previous field for checking whether whole }
  1511. { record was initialized (JM) }
  1512. recsym := srsym;
  1513. { goto next field }
  1514. srsym:=get_next_varsym(def,SymList,symidx);
  1515. if token=_SEMICOLON then
  1516. consume(_SEMICOLON)
  1517. else if (token=_COMMA) and (m_mac in current_settings.modeswitches) then
  1518. consume(_COMMA)
  1519. else
  1520. break;
  1521. end;
  1522. end;
  1523. curoffset:=startoffset;
  1524. { are there any fields left, but don't complain if there only
  1525. come other variant parts after the last initialized field }
  1526. if assigned(srsym) and
  1527. (
  1528. (recsym=nil) or
  1529. (tfieldvarsym(srsym).fieldoffset > tfieldvarsym(recsym).fieldoffset)
  1530. ) then
  1531. Message1(parser_w_skipped_fields_after,sorg);
  1532. if not error then
  1533. begin
  1534. if not(is_packed) then
  1535. fillbytes:=0
  1536. else
  1537. begin
  1538. flush_packed_value(bp);
  1539. recoffset:=align(recoffset,8);
  1540. fillbytes:=def.size-(recoffset div 8);
  1541. end;
  1542. for i:=1 to fillbytes do
  1543. ftcb.emit_tai(Tai_const.Create_8bit(0),u8inttype);
  1544. end;
  1545. ftcb.maybe_end_aggregate(def);
  1546. consume(_RKLAMMER);
  1547. end;
  1548. procedure tasmlisttypedconstbuilder.parse_objectdef(def:tobjectdef);
  1549. var
  1550. n : tnode;
  1551. i : longint;
  1552. obj : tobjectdef;
  1553. srsym : tsym;
  1554. st : tsymtable;
  1555. objoffset : aint;
  1556. s,sorg : TIDString;
  1557. vmtwritten : boolean;
  1558. startoffset:aint;
  1559. begin
  1560. { no support for packed object }
  1561. if is_packed_record_or_object(def) then
  1562. begin
  1563. Message(type_e_no_const_packed_record);
  1564. exit;
  1565. end;
  1566. { only allow nil for implicit pointer object types }
  1567. if is_implicit_pointer_object_type(def) then
  1568. begin
  1569. n:=comp_expr([ef_accept_equal]);
  1570. if n.nodetype<>niln then
  1571. begin
  1572. Message(parser_e_type_const_not_possible);
  1573. consume_all_until(_SEMICOLON);
  1574. end
  1575. else
  1576. ftcb.emit_tai(Tai_const.Create_sym(nil),def);
  1577. n.free;
  1578. exit;
  1579. end;
  1580. { for objects we allow it only if it doesn't contain a vmt }
  1581. if (oo_has_vmt in def.objectoptions) and
  1582. (m_fpc in current_settings.modeswitches) then
  1583. begin
  1584. Message(parser_e_type_object_constants);
  1585. exit;
  1586. end;
  1587. ftcb.maybe_begin_aggregate(def);
  1588. consume(_LKLAMMER);
  1589. startoffset:=curoffset;
  1590. objoffset:=0;
  1591. vmtwritten:=false;
  1592. while token<>_RKLAMMER do
  1593. begin
  1594. s:=pattern;
  1595. sorg:=orgpattern;
  1596. consume(_ID);
  1597. consume(_COLON);
  1598. srsym:=nil;
  1599. obj:=tobjectdef(def);
  1600. st:=obj.symtable;
  1601. while (srsym=nil) and assigned(st) do
  1602. begin
  1603. srsym:=tsym(st.Find(s));
  1604. if assigned(obj) then
  1605. obj:=obj.childof;
  1606. if assigned(obj) then
  1607. st:=obj.symtable
  1608. else
  1609. st:=nil;
  1610. end;
  1611. if (srsym=nil) or
  1612. (srsym.typ<>fieldvarsym) then
  1613. begin
  1614. if (srsym=nil) then
  1615. Message1(sym_e_id_not_found,sorg)
  1616. else
  1617. Message1(sym_e_illegal_field,sorg);
  1618. consume_all_until(_RKLAMMER);
  1619. break;
  1620. end
  1621. else
  1622. with tfieldvarsym(srsym) do
  1623. begin
  1624. { check position }
  1625. if fieldoffset<objoffset then
  1626. message(parser_e_invalid_record_const);
  1627. { check in VMT needs to be added for TP mode }
  1628. if not(vmtwritten) and
  1629. not(m_fpc in current_settings.modeswitches) and
  1630. (oo_has_vmt in def.objectoptions) and
  1631. (def.vmt_offset<fieldoffset) then
  1632. begin
  1633. ftcb.next_field:=tfieldvarsym(def.vmt_field);
  1634. ftcb.emit_tai(tai_const.createname(def.vmt_mangledname,AT_DATA,0),tfieldvarsym(def.vmt_field).vardef);
  1635. objoffset:=def.vmt_offset+tfieldvarsym(def.vmt_field).vardef.size;
  1636. vmtwritten:=true;
  1637. end;
  1638. ftcb.next_field:=tfieldvarsym(srsym);
  1639. { new position }
  1640. objoffset:=fieldoffset+vardef.size;
  1641. { read the data }
  1642. curoffset:=startoffset+fieldoffset;
  1643. read_typed_const_data(vardef);
  1644. if not try_to_consume(_SEMICOLON) then
  1645. break;
  1646. end;
  1647. end;
  1648. curoffset:=startoffset;
  1649. if not(m_fpc in current_settings.modeswitches) and
  1650. (oo_has_vmt in def.objectoptions) and
  1651. (def.vmt_offset>=objoffset) then
  1652. begin
  1653. for i:=1 to def.vmt_offset-objoffset do
  1654. ftcb.emit_tai(tai_const.create_8bit(0),u8inttype);
  1655. // TODO VMT type proper tdef?
  1656. ftcb.emit_tai(tai_const.createname(def.vmt_mangledname,AT_DATA,0),voidpointertype);
  1657. { this is more general }
  1658. objoffset:=def.vmt_offset + sizeof(pint);
  1659. end;
  1660. ftcb.maybe_end_aggregate(def);
  1661. consume(_RKLAMMER);
  1662. end;
  1663. procedure tasmlisttypedconstbuilder.parse_into_asmlist;
  1664. begin
  1665. read_typed_const_data(tcsym.vardef);
  1666. end;
  1667. { tnodetreetypedconstbuilder }
  1668. procedure tnodetreetypedconstbuilder.parse_arraydef(def: tarraydef);
  1669. var
  1670. n : tnode;
  1671. i : longint;
  1672. orgbase: tnode;
  1673. begin
  1674. { dynamic array nil }
  1675. if is_dynamic_array(def) then
  1676. begin
  1677. { Only allow nil initialization }
  1678. consume(_NIL);
  1679. addstatement(statmnt,cassignmentnode.create_internal(basenode,cnilnode.create));
  1680. basenode:=nil;
  1681. end
  1682. { array const between brackets }
  1683. else if try_to_consume(_LKLAMMER) then
  1684. begin
  1685. orgbase:=basenode;
  1686. for i:=def.lowrange to def.highrange-1 do
  1687. begin
  1688. basenode:=cvecnode.create(orgbase.getcopy,ctypeconvnode.create_explicit(genintconstnode(i),tarraydef(def).rangedef));
  1689. read_typed_const_data(def.elementdef);
  1690. if token=_RKLAMMER then
  1691. begin
  1692. Message1(parser_e_more_array_elements_expected,tostr(def.highrange-i));
  1693. consume(_RKLAMMER);
  1694. exit;
  1695. end
  1696. else
  1697. consume(_COMMA);
  1698. end;
  1699. basenode:=cvecnode.create(orgbase,ctypeconvnode.create_explicit(genintconstnode(def.highrange),tarraydef(def).rangedef));
  1700. read_typed_const_data(def.elementdef);
  1701. consume(_RKLAMMER);
  1702. end
  1703. { if array of char then we allow also a string }
  1704. else if is_anychar(def.elementdef) then
  1705. begin
  1706. n:=comp_expr([ef_accept_equal]);
  1707. addstatement(statmnt,cassignmentnode.create_internal(basenode,n));
  1708. basenode:=nil;
  1709. end
  1710. else
  1711. begin
  1712. { we want the ( }
  1713. consume(_LKLAMMER);
  1714. end;
  1715. end;
  1716. procedure tnodetreetypedconstbuilder.parse_procvardef(def: tprocvardef);
  1717. begin
  1718. addstatement(statmnt,cassignmentnode.create_internal(basenode,comp_expr([ef_accept_equal])));
  1719. basenode:=nil;
  1720. end;
  1721. procedure tnodetreetypedconstbuilder.parse_recorddef(def: trecorddef);
  1722. var
  1723. n,n2 : tnode;
  1724. SymList:TFPHashObjectList;
  1725. orgbasenode : tnode;
  1726. symidx : longint;
  1727. recsym,
  1728. srsym : tsym;
  1729. sorg,s : TIDString;
  1730. recoffset : aint;
  1731. error,
  1732. is_packed: boolean;
  1733. procedure handle_stringconstn;
  1734. begin
  1735. addstatement(statmnt,cassignmentnode.create_internal(basenode,n));
  1736. basenode:=nil;
  1737. n:=nil;
  1738. end;
  1739. begin
  1740. { GUID }
  1741. if (def=rec_tguid) and (token=_ID) then
  1742. begin
  1743. n:=comp_expr([ef_accept_equal]);
  1744. if n.nodetype=stringconstn then
  1745. handle_stringconstn
  1746. else
  1747. begin
  1748. inserttypeconv(n,rec_tguid);
  1749. if n.nodetype=guidconstn then
  1750. begin
  1751. n2:=cstringconstnode.createstr(guid2string(tguidconstnode(n).value));
  1752. n.free;
  1753. n:=n2;
  1754. handle_stringconstn;
  1755. end
  1756. else
  1757. Message(parser_e_illegal_expression);
  1758. end;
  1759. n.free;
  1760. exit;
  1761. end;
  1762. if (def=rec_tguid) and ((token=_CSTRING) or (token=_CCHAR)) then
  1763. begin
  1764. n:=comp_expr([ef_accept_equal]);
  1765. inserttypeconv(n,cshortstringtype);
  1766. if n.nodetype=stringconstn then
  1767. handle_stringconstn
  1768. else
  1769. Message(parser_e_illegal_expression);
  1770. n.free;
  1771. exit;
  1772. end;
  1773. { bitpacked record? }
  1774. is_packed:=is_packed_record_or_object(def);
  1775. { normal record }
  1776. consume(_LKLAMMER);
  1777. recoffset:=0;
  1778. sorg:='';
  1779. symidx:=0;
  1780. symlist:=def.symtable.SymList;
  1781. srsym:=get_next_varsym(def,symlist,symidx);
  1782. recsym := nil;
  1783. orgbasenode:=basenode;
  1784. basenode:=nil;
  1785. while token<>_RKLAMMER do
  1786. begin
  1787. s:=pattern;
  1788. sorg:=orgpattern;
  1789. consume(_ID);
  1790. consume(_COLON);
  1791. error := false;
  1792. recsym := tsym(def.symtable.Find(s));
  1793. if not assigned(recsym) then
  1794. begin
  1795. Message1(sym_e_illegal_field,sorg);
  1796. error := true;
  1797. end;
  1798. if (not error) and
  1799. (not assigned(srsym) or
  1800. (s <> srsym.name)) then
  1801. { possible variant record (JM) }
  1802. begin
  1803. { All parts of a variant start at the same offset }
  1804. { Also allow jumping from one variant part to another, }
  1805. { as long as the offsets match }
  1806. if (assigned(srsym) and
  1807. (tfieldvarsym(recsym).fieldoffset = tfieldvarsym(srsym).fieldoffset)) or
  1808. { srsym is not assigned after parsing w2 in the }
  1809. { typed const in the next example: }
  1810. { type tr = record case byte of }
  1811. { 1: (l1,l2: dword); }
  1812. { 2: (w1,w2: word); }
  1813. { end; }
  1814. { const r: tr = (w1:1;w2:1;l2:5); }
  1815. (tfieldvarsym(recsym).fieldoffset = recoffset) then
  1816. begin
  1817. srsym:=recsym;
  1818. { symidx should contain the next symbol id to search }
  1819. symidx:=SymList.indexof(srsym)+1;
  1820. end
  1821. { going backwards isn't allowed in any mode }
  1822. else if (tfieldvarsym(recsym).fieldoffset<recoffset) then
  1823. begin
  1824. Message(parser_e_invalid_record_const);
  1825. error := true;
  1826. end
  1827. { Delphi allows you to skip fields }
  1828. else if (m_delphi in current_settings.modeswitches) then
  1829. begin
  1830. Message1(parser_w_skipped_fields_before,sorg);
  1831. srsym := recsym;
  1832. end
  1833. { FPC and TP don't }
  1834. else
  1835. begin
  1836. Message1(parser_e_skipped_fields_before,sorg);
  1837. error := true;
  1838. end;
  1839. end;
  1840. if error then
  1841. consume_all_until(_SEMICOLON)
  1842. else
  1843. begin
  1844. { skipping fill bytes happens automatically, since we only
  1845. initialize the defined fields }
  1846. { new position }
  1847. recoffset:=tfieldvarsym(srsym).fieldoffset;
  1848. if not(is_packed) then
  1849. inc(recoffset,tfieldvarsym(srsym).vardef.size)
  1850. else
  1851. inc(recoffset,tfieldvarsym(srsym).vardef.packedbitsize);
  1852. { read the data }
  1853. if is_packed and
  1854. { only orddefs and enumdefs are bitpacked, as in gcc/gpc }
  1855. not(tfieldvarsym(srsym).vardef.typ in [orddef,enumdef]) then
  1856. recoffset:=align(recoffset,8);
  1857. basenode:=csubscriptnode.create(srsym,orgbasenode.getcopy);
  1858. read_typed_const_data(tfieldvarsym(srsym).vardef);
  1859. { keep previous field for checking whether whole }
  1860. { record was initialized (JM) }
  1861. recsym := srsym;
  1862. { goto next field }
  1863. srsym:=get_next_varsym(def,SymList,symidx);
  1864. if token=_SEMICOLON then
  1865. consume(_SEMICOLON)
  1866. else if (token=_COMMA) and (m_mac in current_settings.modeswitches) then
  1867. consume(_COMMA)
  1868. else
  1869. break;
  1870. end;
  1871. end;
  1872. { are there any fields left, but don't complain if there only
  1873. come other variant parts after the last initialized field }
  1874. if assigned(srsym) and
  1875. (
  1876. (recsym=nil) or
  1877. (tfieldvarsym(srsym).fieldoffset > tfieldvarsym(recsym).fieldoffset)
  1878. ) then
  1879. Message1(parser_w_skipped_fields_after,sorg);
  1880. orgbasenode.free;
  1881. basenode:=nil;
  1882. consume(_RKLAMMER);
  1883. end;
  1884. procedure tnodetreetypedconstbuilder.parse_objectdef(def: tobjectdef);
  1885. var
  1886. n,
  1887. orgbasenode : tnode;
  1888. obj : tobjectdef;
  1889. srsym : tsym;
  1890. st : tsymtable;
  1891. objoffset : aint;
  1892. s,sorg : TIDString;
  1893. begin
  1894. { no support for packed object }
  1895. if is_packed_record_or_object(def) then
  1896. begin
  1897. Message(type_e_no_const_packed_record);
  1898. exit;
  1899. end;
  1900. { only allow nil for implicit pointer object types }
  1901. if is_implicit_pointer_object_type(def) then
  1902. begin
  1903. n:=comp_expr([ef_accept_equal]);
  1904. if n.nodetype<>niln then
  1905. begin
  1906. Message(parser_e_type_const_not_possible);
  1907. consume_all_until(_SEMICOLON);
  1908. end
  1909. else
  1910. begin
  1911. addstatement(statmnt,cassignmentnode.create_internal(basenode,n));
  1912. n:=nil;
  1913. basenode:=nil;
  1914. end;
  1915. n.free;
  1916. exit;
  1917. end;
  1918. { for objects we allow it only if it doesn't contain a vmt }
  1919. if (oo_has_vmt in def.objectoptions) and
  1920. (m_fpc in current_settings.modeswitches) then
  1921. begin
  1922. Message(parser_e_type_object_constants);
  1923. exit;
  1924. end;
  1925. consume(_LKLAMMER);
  1926. objoffset:=0;
  1927. orgbasenode:=basenode;
  1928. basenode:=nil;
  1929. while token<>_RKLAMMER do
  1930. begin
  1931. s:=pattern;
  1932. sorg:=orgpattern;
  1933. consume(_ID);
  1934. consume(_COLON);
  1935. srsym:=nil;
  1936. obj:=tobjectdef(def);
  1937. st:=obj.symtable;
  1938. while (srsym=nil) and assigned(st) do
  1939. begin
  1940. srsym:=tsym(st.Find(s));
  1941. if assigned(obj) then
  1942. obj:=obj.childof;
  1943. if assigned(obj) then
  1944. st:=obj.symtable
  1945. else
  1946. st:=nil;
  1947. end;
  1948. if (srsym=nil) or
  1949. (srsym.typ<>fieldvarsym) then
  1950. begin
  1951. if (srsym=nil) then
  1952. Message1(sym_e_id_not_found,sorg)
  1953. else
  1954. Message1(sym_e_illegal_field,sorg);
  1955. consume_all_until(_RKLAMMER);
  1956. break;
  1957. end
  1958. else
  1959. with tfieldvarsym(srsym) do
  1960. begin
  1961. { check position }
  1962. if fieldoffset<objoffset then
  1963. message(parser_e_invalid_record_const);
  1964. { new position }
  1965. objoffset:=fieldoffset+vardef.size;
  1966. { read the data }
  1967. basenode:=csubscriptnode.create(srsym,orgbasenode.getcopy);
  1968. read_typed_const_data(vardef);
  1969. if not try_to_consume(_SEMICOLON) then
  1970. break;
  1971. end;
  1972. end;
  1973. consume(_RKLAMMER);
  1974. end;
  1975. procedure tnodetreetypedconstbuilder.tc_emit_orddef(def: torddef; var node: tnode);
  1976. begin
  1977. addstatement(statmnt,cassignmentnode.create_internal(basenode,node));
  1978. basenode:=nil;
  1979. node:=nil;
  1980. end;
  1981. procedure tnodetreetypedconstbuilder.tc_emit_floatdef(def: tfloatdef; var node: tnode);
  1982. begin
  1983. addstatement(statmnt,cassignmentnode.create_internal(basenode,node));
  1984. basenode:=nil;
  1985. node:=nil;
  1986. end;
  1987. procedure tnodetreetypedconstbuilder.tc_emit_classrefdef(def: tclassrefdef; var node: tnode);
  1988. begin
  1989. addstatement(statmnt,cassignmentnode.create_internal(basenode,node));
  1990. basenode:=nil;
  1991. node:=nil;
  1992. end;
  1993. procedure tnodetreetypedconstbuilder.tc_emit_pointerdef(def: tpointerdef; var node: tnode);
  1994. begin
  1995. addstatement(statmnt,cassignmentnode.create_internal(basenode,node));
  1996. basenode:=nil;
  1997. node:=nil;
  1998. end;
  1999. procedure tnodetreetypedconstbuilder.tc_emit_setdef(def: tsetdef; var node: tnode);
  2000. begin
  2001. addstatement(statmnt,cassignmentnode.create_internal(basenode,node));
  2002. basenode:=nil;
  2003. node:=nil;
  2004. end;
  2005. procedure tnodetreetypedconstbuilder.tc_emit_enumdef(def: tenumdef; var node: tnode);
  2006. begin
  2007. addstatement(statmnt,cassignmentnode.create_internal(basenode,node));
  2008. basenode:=nil;
  2009. node:=nil;
  2010. end;
  2011. procedure tnodetreetypedconstbuilder.tc_emit_stringdef(def: tstringdef; var node: tnode);
  2012. begin
  2013. addstatement(statmnt,cassignmentnode.create_internal(basenode,node));
  2014. basenode:=nil;
  2015. node:=nil;
  2016. end;
  2017. constructor tnodetreetypedconstbuilder.create(sym: tstaticvarsym; previnit: tnode);
  2018. begin
  2019. inherited create(sym);
  2020. basenode:=cloadnode.create(sym,sym.owner);
  2021. resultblock:=internalstatements(statmnt);
  2022. if assigned(previnit) then
  2023. addstatement(statmnt,previnit);
  2024. end;
  2025. destructor tnodetreetypedconstbuilder.destroy;
  2026. begin
  2027. freeandnil(basenode);
  2028. freeandnil(resultblock);
  2029. inherited destroy;
  2030. end;
  2031. function tnodetreetypedconstbuilder.parse_into_nodetree: tnode;
  2032. begin
  2033. read_typed_const_data(tcsym.vardef);
  2034. result:=self.resultblock;
  2035. self.resultblock:=nil;
  2036. end;
  2037. begin
  2038. { default to asmlist version, best for most targets }
  2039. ctypedconstbuilder:=tasmlisttypedconstbuilder;
  2040. end.