2
0

ngtcon.pas 88 KB

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