ngtcon.pas 80 KB

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