ngtcon.pas 79 KB

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