ngtcon.pas 79 KB

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