ngtcon.pas 83 KB

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