ngtcon.pas 80 KB

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