ngtcon.pas 84 KB

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