ngtcon.pas 88 KB

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