ngtcon.pas 84 KB

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