ngtcon.pas 80 KB

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