ngtcon.pas 80 KB

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