ngtcon.pas 79 KB

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