ngtcon.pas 79 KB

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