ngtcon.pas 87 KB

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