ngtcon.pas 89 KB

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