ngtcon.pas 79 KB

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