ngtcon.pas 83 KB

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