ngtcon.pas 84 KB

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