2
0

ngtcon.pas 86 KB

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