ngtcon.pas 84 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288
  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. { work around broken x86 shifting }
  298. if (AIntBits<>bp.packedbitsize) and
  299. (bp.curbitoffset<AIntBits) then
  300. bp.curval:=bp.curval or ((value shl (AIntBits-bp.packedbitsize)) shr bp.curbitoffset);
  301. shiftcount:=((AIntBits-bp.packedbitsize)-bp.curbitoffset);
  302. { carry-over to the next element? }
  303. if (shiftcount<0) then
  304. begin
  305. if shiftcount>=AIntBits then
  306. bp.nextval:=(value and ((aword(1) shl (-shiftcount))-1)) shl
  307. (AIntBits+shiftcount)
  308. else
  309. bp.nextval:=0
  310. end
  311. end
  312. else
  313. begin
  314. { bitpacked format: right aligned (i.e., "little endian bitness") }
  315. { work around broken x86 shifting }
  316. if bp.curbitoffset<AIntBits then
  317. bp.curval:=bp.curval or (value shl bp.curbitoffset);
  318. { carry-over to the next element? }
  319. if (bp.curbitoffset+bp.packedbitsize>AIntBits) then
  320. if bp.curbitoffset>0 then
  321. bp.nextval:=value shr (AIntBits-bp.curbitoffset)
  322. else
  323. bp.nextval:=0;
  324. end;
  325. inc(bp.curbitoffset,bp.packedbitsize);
  326. end;
  327. procedure tasmlisttypedconstbuilder.flush_packed_value(var bp: tbitpackedval);
  328. var
  329. bitstowrite: longint;
  330. writeval : {$ifdef CPU8BITALU}smallint{$else}aint{$endif};
  331. begin
  332. if (bp.curbitoffset < AIntBits) then
  333. begin
  334. { forced flush -> write multiple of a byte }
  335. bitstowrite:=align(bp.curbitoffset,8);
  336. bp.curbitoffset:=0;
  337. end
  338. else
  339. begin
  340. bitstowrite:=AIntBits;
  341. dec(bp.curbitoffset,AIntBits);
  342. end;
  343. while (bitstowrite>=8) do
  344. begin
  345. if (target_info.endian=endian_little) then
  346. begin
  347. { write lowest byte }
  348. writeval:=byte(bp.curval);
  349. bp.curval:=bp.curval shr 8;
  350. end
  351. else
  352. begin
  353. { write highest byte }
  354. writeval:=bp.curval shr (AIntBits-8);
  355. {$push}{$r-,q-}
  356. bp.curval:=bp.curval shl 8;
  357. {$pop}
  358. end;
  359. ftcb.emit_tai(tai_const.create_8bit(writeval),u8inttype);
  360. dec(bitstowrite,8);
  361. end;
  362. bp.curval:=bp.nextval;
  363. bp.nextval:=0;
  364. end;
  365. {$pop}
  366. { parses a packed array constant }
  367. procedure tasmlisttypedconstbuilder.parse_packed_array_def(def: tarraydef);
  368. var
  369. i : {$ifdef CPU8BITALU}smallint{$else}aint{$endif};
  370. bp : tbitpackedval;
  371. begin
  372. if not(def.elementdef.typ in [orddef,enumdef]) then
  373. internalerror(2007022010);
  374. ftcb.maybe_begin_aggregate(def);
  375. { begin of the array }
  376. consume(_LKLAMMER);
  377. initbitpackval(bp,def.elepackedbitsize);
  378. i:=def.lowrange;
  379. { can't use for-loop, fails when cross-compiling from }
  380. { 32 to 64 bit because i is then 64 bit }
  381. while (i<def.highrange) do
  382. begin
  383. { get next item of the packed array }
  384. if not parse_single_packed_const(def.elementdef,bp) then
  385. exit;
  386. consume(_COMMA);
  387. inc(i);
  388. end;
  389. { final item }
  390. if not parse_single_packed_const(def.elementdef,bp) then
  391. exit;
  392. { flush final incomplete value if necessary }
  393. if (bp.curbitoffset <> 0) then
  394. flush_packed_value(bp);
  395. ftcb.maybe_end_aggregate(def);
  396. consume(_RKLAMMER);
  397. end;
  398. constructor tasmlisttypedconstbuilder.create(sym: tstaticvarsym);
  399. begin
  400. inherited;
  401. fsym:=sym;
  402. ftcb:=ctai_typedconstbuilder.create([tcalo_make_dead_strippable,tcalo_apply_constalign]);
  403. fdatalist:=tasmlist.create;
  404. curoffset:=0;
  405. end;
  406. destructor tasmlisttypedconstbuilder.Destroy;
  407. begin
  408. fdatalist.free;
  409. ftcb.free;
  410. inherited Destroy;
  411. end;
  412. procedure tasmlisttypedconstbuilder.tc_emit_stringdef(def: tstringdef; var node: tnode);
  413. var
  414. strlength : {$ifdef CPU8BITALU}smallint{$else}aint{$endif};
  415. strval : pchar;
  416. ll : tasmlabofs;
  417. ca : pchar;
  418. winlike : boolean;
  419. hsym : tconstsym;
  420. begin
  421. strval:='';
  422. { load strval and strlength of the constant tree }
  423. if (node.nodetype=stringconstn) or is_wide_or_unicode_string(def) or is_constwidecharnode(node) or
  424. ((node.nodetype=typen) and is_interfacecorba(ttypenode(node).typedef)) or
  425. is_constcharnode(node) then
  426. begin
  427. { convert to the expected string type so that
  428. for widestrings strval is a pcompilerwidestring }
  429. inserttypeconv(node,def);
  430. if (not codegenerror) and
  431. (node.nodetype=stringconstn) then
  432. begin
  433. strlength:=tstringconstnode(node).len;
  434. strval:=tstringconstnode(node).value_str;
  435. { the def may have changed from e.g. RawByteString to
  436. AnsiString(CP_ACP) }
  437. if node.resultdef.typ=stringdef then
  438. def:=tstringdef(node.resultdef)
  439. else
  440. internalerror(2014010501);
  441. end
  442. else
  443. begin
  444. { an error occurred trying to convert the result to a string }
  445. strlength:=-1;
  446. { it's possible that the type conversion could not be
  447. evaluated at compile-time }
  448. if not codegenerror then
  449. CGMessage(parser_e_widestring_to_ansi_compile_time);
  450. end;
  451. end
  452. else if is_constresourcestringnode(node) then
  453. begin
  454. hsym:=tconstsym(tloadnode(node).symtableentry);
  455. strval:=pchar(hsym.value.valueptr);
  456. strlength:=hsym.value.len;
  457. { Delphi-compatible (mis)feature:
  458. Link AnsiString constants to their initializing resourcestring,
  459. enabling them to be (re)translated at runtime.
  460. Wide/UnicodeString are currently rejected above (with incorrect error message).
  461. ShortStrings cannot be handled unless another table is built for them;
  462. considering this acceptable, because Delphi rejects them altogether.
  463. }
  464. if (not is_shortstring(def)) and
  465. ((tcsym.owner.symtablelevel<=main_program_level) or
  466. (current_old_block_type=bt_const)) then
  467. begin
  468. current_asmdata.ResStrInits.Concat(
  469. TTCInitItem.Create(tcsym,curoffset,
  470. current_asmdata.RefAsmSymbol(make_mangledname('RESSTR',hsym.owner,hsym.name),AT_DATA),charpointertype)
  471. );
  472. Include(tcsym.varoptions,vo_force_finalize);
  473. end;
  474. end
  475. else
  476. begin
  477. Message(parser_e_illegal_expression);
  478. strlength:=-1;
  479. end;
  480. if strlength>=0 then
  481. begin
  482. case def.stringtype of
  483. st_shortstring:
  484. begin
  485. ftcb.maybe_begin_aggregate(def);
  486. if strlength>=def.size then
  487. begin
  488. message2(parser_w_string_too_long,strpas(strval),tostr(def.size-1));
  489. strlength:=def.size-1;
  490. end;
  491. ftcb.emit_tai(Tai_const.Create_8bit(strlength),cansichartype);
  492. { room for the string data + terminating #0 }
  493. getmem(ca,def.size);
  494. move(strval^,ca^,strlength);
  495. { zero-terminate and fill with spaces if size is shorter }
  496. fillchar(ca[strlength],def.size-strlength-1,' ');
  497. ca[strlength]:=#0;
  498. ca[def.size-1]:=#0;
  499. ftcb.emit_tai(Tai_string.Create_pchar(ca,def.size-1),carraydef.getreusable(cansichartype,def.size-1));
  500. ftcb.maybe_end_aggregate(def);
  501. end;
  502. st_ansistring:
  503. begin
  504. { an empty ansi string is nil! }
  505. if (strlength=0) then
  506. begin
  507. ll.lab:=nil;
  508. ll.ofs:=0;
  509. end
  510. else
  511. ll:=ftcb.emit_ansistring_const(fdatalist,strval,strlength,def.encoding);
  512. ftcb.emit_string_offset(ll,strlength,def.stringtype,false,charpointertype);
  513. end;
  514. st_unicodestring,
  515. st_widestring:
  516. begin
  517. { an empty wide/unicode string is nil! }
  518. if (strlength=0) then
  519. begin
  520. ll.lab:=nil;
  521. ll.ofs:=0;
  522. winlike:=false;
  523. end
  524. else
  525. begin
  526. winlike:=(def.stringtype=st_widestring) and (tf_winlikewidestring in target_info.flags);
  527. ll:=ftcb.emit_unicodestring_const(fdatalist,
  528. strval,
  529. def.encoding,
  530. winlike);
  531. { Collect Windows widestrings that need initialization at startup.
  532. Local initialized vars are excluded because they are initialized
  533. at function entry instead. }
  534. if winlike and
  535. ((tcsym.owner.symtablelevel<=main_program_level) or
  536. (current_old_block_type=bt_const)) then
  537. begin
  538. if ll.ofs<>0 then
  539. internalerror(2012051704);
  540. current_asmdata.WideInits.Concat(
  541. TTCInitItem.Create(tcsym,curoffset,ll.lab,widecharpointertype)
  542. );
  543. ll.lab:=nil;
  544. ll.ofs:=0;
  545. Include(tcsym.varoptions,vo_force_finalize);
  546. end;
  547. end;
  548. ftcb.emit_string_offset(ll,strlength,def.stringtype,winlike,widecharpointertype);
  549. end;
  550. else
  551. internalerror(200107081);
  552. end;
  553. end;
  554. end;
  555. procedure tasmlisttypedconstbuilder.tc_emit_orddef(def: torddef; var node: tnode);
  556. var
  557. intvalue: tconstexprint;
  558. procedure do_error;
  559. begin
  560. if is_constnode(node) then
  561. IncompatibleTypes(node.resultdef, def)
  562. else if not(parse_generic) then
  563. Message(parser_e_illegal_expression);
  564. end;
  565. begin
  566. case def.ordtype of
  567. pasbool1,
  568. pasbool8,
  569. bool8bit,
  570. pasbool16,
  571. bool16bit,
  572. pasbool32,
  573. bool32bit,
  574. pasbool64,
  575. bool64bit:
  576. begin
  577. if is_constboolnode(node) then
  578. begin
  579. adaptrange(def,tordconstnode(node).value,false,false,cs_check_range in current_settings.localswitches);
  580. ftcb.emit_ord_const(tordconstnode(node).value.svalue,def)
  581. end
  582. else
  583. do_error;
  584. end;
  585. uchar :
  586. begin
  587. if is_constwidecharnode(node) then
  588. inserttypeconv(node,cansichartype);
  589. if is_constcharnode(node) or
  590. ((m_delphi in current_settings.modeswitches) and
  591. is_constwidecharnode(node) and
  592. (tordconstnode(node).value <= 255)) then
  593. ftcb.emit_ord_const(byte(tordconstnode(node).value.svalue),def)
  594. else
  595. do_error;
  596. end;
  597. uwidechar :
  598. begin
  599. if is_constcharnode(node) then
  600. inserttypeconv(node,cwidechartype);
  601. if is_constwidecharnode(node) then
  602. ftcb.emit_ord_const(word(tordconstnode(node).value.svalue),def)
  603. else
  604. do_error;
  605. end;
  606. s8bit,u8bit,
  607. u16bit,s16bit,
  608. s32bit,u32bit,
  609. s64bit,u64bit :
  610. begin
  611. if is_constintnode(node) then
  612. begin
  613. adaptrange(def,tordconstnode(node).value,false,false,cs_check_range in current_settings.localswitches);
  614. ftcb.emit_ord_const(tordconstnode(node).value.svalue,def);
  615. end
  616. else
  617. do_error;
  618. end;
  619. scurrency:
  620. begin
  621. if is_constintnode(node) then
  622. intvalue:=tordconstnode(node).value*10000
  623. { allow bootstrapping }
  624. else if is_constrealnode(node) then
  625. intvalue:=PInt64(@trealconstnode(node).value_currency)^
  626. else
  627. begin
  628. intvalue:=0;
  629. IncompatibleTypes(node.resultdef, def);
  630. end;
  631. ftcb.emit_ord_const(intvalue,def);
  632. end;
  633. else
  634. internalerror(200611052);
  635. end;
  636. end;
  637. procedure tasmlisttypedconstbuilder.tc_emit_floatdef(def: tfloatdef; var node: tnode);
  638. var
  639. value : bestreal;
  640. begin
  641. value:=0.0;
  642. if is_constrealnode(node) then
  643. value:=trealconstnode(node).value_real
  644. else if is_constintnode(node) then
  645. value:=tordconstnode(node).value
  646. else if is_constnode(node) then
  647. IncompatibleTypes(node.resultdef, def)
  648. else
  649. Message(parser_e_illegal_expression);
  650. case def.floattype of
  651. s32real :
  652. ftcb.emit_tai(tai_realconst.create_s32real(ts32real(value)),def);
  653. s64real :
  654. {$ifdef ARM}
  655. if is_double_hilo_swapped then
  656. ftcb.emit_tai(tai_realconst.create_s64real_hiloswapped(ts64real(value)),def)
  657. else
  658. {$endif ARM}
  659. ftcb.emit_tai(tai_realconst.create_s64real(ts64real(value)),def);
  660. s80real :
  661. ftcb.emit_tai(tai_realconst.create_s80real(value,s80floattype.size),def);
  662. sc80real :
  663. ftcb.emit_tai(tai_realconst.create_s80real(value,sc80floattype.size),def);
  664. s64comp :
  665. { the round is necessary for native compilers where comp isn't a float }
  666. ftcb.emit_tai(tai_realconst.create_s64compreal(round(value)),def);
  667. s64currency:
  668. ftcb.emit_tai(tai_realconst.create_s64compreal(round(value*10000)),def);
  669. s128real:
  670. ftcb.emit_tai(tai_realconst.create_s128real(value),def);
  671. else
  672. internalerror(200611053);
  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
  1074. asmsym:=current_asmdata.DefineAsmSymbol(fsym.mangledname,AB_LOCAL,AT_DATA,tcsym.vardef);
  1075. if vo_has_section in fsym.varoptions then
  1076. begin
  1077. sec:=sec_user;
  1078. secname:=fsym.section;
  1079. end
  1080. else
  1081. begin
  1082. { Certain types like windows WideString are initialized at runtime and cannot
  1083. be placed into readonly memory }
  1084. if (fsym.varspez=vs_const) and
  1085. not (vo_force_finalize in fsym.varoptions) then
  1086. sec:=sec_rodata
  1087. else
  1088. sec:=sec_data;
  1089. secname:=asmsym.Name;
  1090. end;
  1091. reslist:=ftcb.get_final_asmlist(asmsym,fsym.vardef,sec,secname,fsym.vardef.alignment);
  1092. if addstabx then
  1093. begin
  1094. { see same code in ncgutil.insertbssdata }
  1095. reslist.insert(tai_directive.Create(asd_reference,fsym.name));
  1096. reslist.insert(tai_symbol.Create(current_asmdata.DefineAsmSymbol(fsym.name,AB_LOCAL,AT_DATA,tcsym.vardef),0));
  1097. end;
  1098. datalist:=fdatalist;
  1099. end;
  1100. procedure tasmlisttypedconstbuilder.parse_arraydef(def:tarraydef);
  1101. const
  1102. LKlammerToken: array[Boolean] of TToken = (_LKLAMMER, _LECKKLAMMER);
  1103. RKlammerToken: array[Boolean] of TToken = (_RKLAMMER, _RECKKLAMMER);
  1104. var
  1105. n : tnode;
  1106. i : longint;
  1107. len : asizeint;
  1108. ch : array[0..1] of char;
  1109. ca : pbyte;
  1110. int_const: tai_const;
  1111. char_size: integer;
  1112. dyncount,
  1113. oldoffset: asizeint;
  1114. dummy : byte;
  1115. sectype : tasmsectiontype;
  1116. oldtcb,
  1117. datatcb : ttai_typedconstbuilder;
  1118. ll : tasmlabel;
  1119. dyncountloc : ttypedconstplaceholder;
  1120. llofs : tasmlabofs;
  1121. dynarrdef : tdef;
  1122. begin
  1123. { dynamic array }
  1124. if is_dynamic_array(def) then
  1125. begin
  1126. if try_to_consume(_NIL) then
  1127. begin
  1128. ftcb.emit_tai(Tai_const.Create_sym(nil),def);
  1129. end
  1130. else if try_to_consume(LKlammerToken[m_delphi in current_settings.modeswitches]) then
  1131. begin
  1132. if try_to_consume(RKlammerToken[m_delphi in current_settings.modeswitches]) then
  1133. begin
  1134. ftcb.emit_tai(tai_const.create_sym(nil),def);
  1135. end
  1136. else
  1137. begin
  1138. if fsym.varspez=vs_const then
  1139. sectype:=sec_rodata
  1140. else
  1141. sectype:=sec_data;
  1142. ftcb.start_internal_data_builder(fdatalist,sectype,'',datatcb,ll);
  1143. llofs:=datatcb.begin_dynarray_const(def,ll,dyncountloc);
  1144. dyncount:=0;
  1145. oldtcb:=ftcb;
  1146. ftcb:=datatcb;
  1147. while true do
  1148. begin
  1149. read_typed_const_data(def.elementdef);
  1150. inc(dyncount);
  1151. if try_to_consume(RKlammerToken[m_delphi in current_settings.modeswitches]) then
  1152. break
  1153. else
  1154. consume(_COMMA);
  1155. end;
  1156. ftcb:=oldtcb;
  1157. dynarrdef:=datatcb.end_dynarray_const(def,dyncount,dyncountloc);
  1158. ftcb.finish_internal_data_builder(datatcb,ll,dynarrdef,sizeof(pint));
  1159. ftcb.emit_dynarray_offset(llofs,dyncount,def);
  1160. end;
  1161. end
  1162. else
  1163. consume(_LKLAMMER);
  1164. end
  1165. { packed array constant }
  1166. else if is_packed_array(def) and
  1167. ((def.elepackedbitsize mod 8 <> 0) or
  1168. not ispowerof2(def.elepackedbitsize div 8,i)) then
  1169. begin
  1170. parse_packed_array_def(def);
  1171. end
  1172. { normal array const between brackets }
  1173. else if try_to_consume(_LKLAMMER) then
  1174. begin
  1175. ftcb.maybe_begin_aggregate(def);
  1176. oldoffset:=curoffset;
  1177. curoffset:=0;
  1178. { in case of a generic subroutine, it might be we cannot
  1179. determine the size yet }
  1180. if assigned(current_procinfo) and (df_generic in current_procinfo.procdef.defoptions) then
  1181. begin
  1182. while true do
  1183. begin
  1184. read_typed_const_data(def.elementdef);
  1185. if token=_RKLAMMER then
  1186. begin
  1187. consume(_RKLAMMER);
  1188. break;
  1189. end
  1190. else
  1191. consume(_COMMA);
  1192. end;
  1193. end
  1194. else
  1195. begin
  1196. for i:=def.lowrange to def.highrange-1 do
  1197. begin
  1198. read_typed_const_data(def.elementdef);
  1199. Inc(curoffset,def.elementdef.size);
  1200. if token=_RKLAMMER then
  1201. begin
  1202. Message1(parser_e_more_array_elements_expected,tostr(def.highrange-i));
  1203. consume(_RKLAMMER);
  1204. exit;
  1205. end
  1206. else
  1207. consume(_COMMA);
  1208. end;
  1209. read_typed_const_data(def.elementdef);
  1210. consume(_RKLAMMER);
  1211. end;
  1212. curoffset:=oldoffset;
  1213. ftcb.maybe_end_aggregate(def);
  1214. end
  1215. { if array of char then we allow also a string }
  1216. else if is_anychar(def.elementdef) then
  1217. begin
  1218. ftcb.maybe_begin_aggregate(def);
  1219. char_size:=def.elementdef.size;
  1220. n:=comp_expr([ef_accept_equal]);
  1221. if n.nodetype=stringconstn then
  1222. begin
  1223. len:=tstringconstnode(n).len;
  1224. case char_size of
  1225. 1:
  1226. begin
  1227. if (tstringconstnode(n).cst_type in [cst_unicodestring,cst_widestring]) then
  1228. inserttypeconv(n,getansistringdef);
  1229. if n.nodetype<>stringconstn then
  1230. internalerror(2010033003);
  1231. ca:=pointer(tstringconstnode(n).value_str);
  1232. end;
  1233. 2:
  1234. begin
  1235. inserttypeconv(n,cunicodestringtype);
  1236. if n.nodetype<>stringconstn then
  1237. internalerror(2010033003);
  1238. ca:=pointer(pcompilerwidestring(tstringconstnode(n).value_str)^.data)
  1239. end;
  1240. else
  1241. internalerror(2010033005);
  1242. end;
  1243. { For tp7 the maximum lentgh can be 255 }
  1244. if (m_tp7 in current_settings.modeswitches) and
  1245. (len>255) then
  1246. len:=255;
  1247. end
  1248. else if is_constcharnode(n) then
  1249. begin
  1250. case char_size of
  1251. 1:
  1252. ch[0]:=chr(tordconstnode(n).value.uvalue and $ff);
  1253. 2:
  1254. begin
  1255. inserttypeconv(n,cwidechartype);
  1256. if not is_constwidecharnode(n) then
  1257. internalerror(2010033001);
  1258. widechar(ch):=widechar(tordconstnode(n).value.uvalue and $ffff);
  1259. end;
  1260. else
  1261. internalerror(2010033002);
  1262. end;
  1263. ca:=@ch;
  1264. len:=1;
  1265. end
  1266. else if is_constwidecharnode(n) and (current_settings.sourcecodepage<>CP_UTF8) then
  1267. begin
  1268. case char_size of
  1269. 1:
  1270. begin
  1271. inserttypeconv(n,cansichartype);
  1272. if not is_constcharnode(n) then
  1273. internalerror(2010033001);
  1274. ch[0]:=chr(tordconstnode(n).value.uvalue and $ff);
  1275. end;
  1276. 2:
  1277. widechar(ch):=widechar(tordconstnode(n).value.uvalue and $ffff);
  1278. else
  1279. internalerror(2010033002);
  1280. end;
  1281. ca:=@ch;
  1282. len:=1;
  1283. end
  1284. else
  1285. begin
  1286. Message(parser_e_illegal_expression);
  1287. len:=0;
  1288. { avoid crash later on }
  1289. dummy:=0;
  1290. ca:=@dummy;
  1291. end;
  1292. if len>(def.highrange-def.lowrange+1) then
  1293. Message(parser_e_string_larger_array);
  1294. for i:=0 to def.highrange-def.lowrange do
  1295. begin
  1296. if i<len then
  1297. begin
  1298. case char_size of
  1299. 1:
  1300. int_const:=Tai_const.Create_char(char_size,pbyte(ca)^);
  1301. 2:
  1302. int_const:=Tai_const.Create_char(char_size,pword(ca)^);
  1303. else
  1304. internalerror(2010033004);
  1305. end;
  1306. inc(ca, char_size);
  1307. end
  1308. else
  1309. {Fill the remaining positions with #0.}
  1310. int_const:=Tai_const.Create_char(char_size,0);
  1311. ftcb.emit_tai(int_const,def.elementdef)
  1312. end;
  1313. ftcb.maybe_end_aggregate(def);
  1314. n.free;
  1315. end
  1316. else
  1317. begin
  1318. { we want the ( }
  1319. consume(_LKLAMMER);
  1320. end;
  1321. end;
  1322. procedure tasmlisttypedconstbuilder.parse_procvardef(def:tprocvardef);
  1323. var
  1324. tmpn,n : tnode;
  1325. pd : tprocdef;
  1326. procaddrdef: tprocvardef;
  1327. havepd,
  1328. haveblock: boolean;
  1329. begin
  1330. { Procvars and pointers are no longer compatible. }
  1331. { under tp: =nil or =var under fpc: =nil or =@var }
  1332. if try_to_consume(_NIL) then
  1333. begin
  1334. ftcb.maybe_begin_aggregate(def);
  1335. { we need the procdef type called by the procvar here, not the
  1336. procvar record }
  1337. ftcb.emit_tai_procvar2procdef(Tai_const.Create_sym(nil),def);
  1338. if not def.is_addressonly then
  1339. ftcb.emit_tai(Tai_const.Create_sym(nil),voidpointertype);
  1340. ftcb.maybe_end_aggregate(def);
  1341. exit;
  1342. end;
  1343. { you can't assign a value other than NIL to a typed constant }
  1344. { which is a "procedure of object", because this also requires }
  1345. { address of an object/class instance, which is not known at }
  1346. { compile time (JM) }
  1347. if (po_methodpointer in def.procoptions) then
  1348. Message(parser_e_no_procvarobj_const);
  1349. { parse the rest too, so we can continue with error checking }
  1350. getprocvardef:=def;
  1351. n:=comp_expr([ef_accept_equal]);
  1352. getprocvardef:=nil;
  1353. if codegenerror then
  1354. begin
  1355. n.free;
  1356. exit;
  1357. end;
  1358. { let type conversion check everything needed }
  1359. inserttypeconv(n,def);
  1360. if codegenerror then
  1361. begin
  1362. n.free;
  1363. exit;
  1364. end;
  1365. { in case of a nested procdef initialised with a global routine }
  1366. ftcb.maybe_begin_aggregate(def);
  1367. { get the address of the procedure, except if it's a C-block (then we
  1368. we will end up with a record that represents the C-block) }
  1369. if not is_block(def) then
  1370. procaddrdef:=cprocvardef.getreusableprocaddr(def)
  1371. else
  1372. procaddrdef:=def;
  1373. ftcb.queue_init(procaddrdef);
  1374. { remove typeconvs, that will normally insert a lea
  1375. instruction which is not necessary for us }
  1376. while n.nodetype=typeconvn do
  1377. begin
  1378. ftcb.queue_typeconvn(ttypeconvnode(n).left.resultdef,n.resultdef);
  1379. tmpn:=ttypeconvnode(n).left;
  1380. ttypeconvnode(n).left:=nil;
  1381. n.free;
  1382. n:=tmpn;
  1383. end;
  1384. { remove addrn which we also don't need here }
  1385. if n.nodetype=addrn then
  1386. begin
  1387. tmpn:=taddrnode(n).left;
  1388. taddrnode(n).left:=nil;
  1389. n.free;
  1390. n:=tmpn;
  1391. end;
  1392. pd:=nil;
  1393. { we now need to have a loadn with a procsym }
  1394. havepd:=
  1395. (n.nodetype=loadn) and
  1396. (tloadnode(n).symtableentry.typ=procsym);
  1397. { or a staticvarsym representing a block }
  1398. haveblock:=
  1399. (n.nodetype=loadn) and
  1400. (tloadnode(n).symtableentry.typ=staticvarsym) and
  1401. (sp_internal in tloadnode(n).symtableentry.symoptions);
  1402. if havepd or
  1403. haveblock then
  1404. begin
  1405. if havepd then
  1406. begin
  1407. pd:=tloadnode(n).procdef;
  1408. ftcb.queue_emit_proc(pd);
  1409. end
  1410. else
  1411. begin
  1412. ftcb.queue_emit_staticvar(tstaticvarsym(tloadnode(n).symtableentry));
  1413. end;
  1414. { nested procvar typed consts can only be initialised with nil
  1415. (checked above) or with a global procedure (checked here),
  1416. because in other cases we need a valid frame pointer }
  1417. if is_nested_pd(def) then
  1418. begin
  1419. if haveblock or
  1420. is_nested_pd(pd) then
  1421. Message(parser_e_no_procvarnested_const);
  1422. ftcb.emit_tai(Tai_const.Create_sym(nil),voidpointertype);
  1423. end;
  1424. end
  1425. else if n.nodetype=pointerconstn then
  1426. begin
  1427. ftcb.queue_emit_ordconst(tpointerconstnode(n).value,procaddrdef);
  1428. if not def.is_addressonly then
  1429. ftcb.emit_tai(Tai_const.Create_sym(nil),voidpointertype);
  1430. end
  1431. else
  1432. Message(parser_e_illegal_expression);
  1433. ftcb.maybe_end_aggregate(def);
  1434. n.free;
  1435. end;
  1436. procedure tasmlisttypedconstbuilder.parse_recorddef(def:trecorddef);
  1437. var
  1438. n : tnode;
  1439. symidx : longint;
  1440. recsym,
  1441. srsym : tsym;
  1442. hs : string;
  1443. sorg,s : TIDString;
  1444. tmpguid : tguid;
  1445. recoffset,
  1446. fillbytes : {$ifdef CPU8BITALU}smallint{$else}aint{$endif};
  1447. bp : tbitpackedval;
  1448. error,
  1449. is_packed: boolean;
  1450. startoffset: {$ifdef CPU8BITALU}word{$else}aword{$endif};
  1451. procedure handle_stringconstn;
  1452. begin
  1453. hs:=strpas(tstringconstnode(n).value_str);
  1454. if string2guid(hs,tmpguid) then
  1455. ftcb.emit_guid_const(tmpguid)
  1456. else
  1457. Message(parser_e_improper_guid_syntax);
  1458. end;
  1459. var
  1460. i : longint;
  1461. SymList:TFPHashObjectList;
  1462. begin
  1463. { GUID }
  1464. if (def=rec_tguid) and (token=_ID) then
  1465. begin
  1466. n:=comp_expr([ef_accept_equal]);
  1467. if n.nodetype=stringconstn then
  1468. handle_stringconstn
  1469. else
  1470. begin
  1471. inserttypeconv(n,rec_tguid);
  1472. if n.nodetype=guidconstn then
  1473. ftcb.emit_guid_const(tguidconstnode(n).value)
  1474. else
  1475. Message(parser_e_illegal_expression);
  1476. end;
  1477. n.free;
  1478. exit;
  1479. end;
  1480. if (def=rec_tguid) and ((token=_CSTRING) or (token=_CCHAR)) then
  1481. begin
  1482. n:=comp_expr([ef_accept_equal]);
  1483. inserttypeconv(n,cshortstringtype);
  1484. if n.nodetype=stringconstn then
  1485. handle_stringconstn
  1486. else
  1487. Message(parser_e_illegal_expression);
  1488. n.free;
  1489. exit;
  1490. end;
  1491. ftcb.maybe_begin_aggregate(def);
  1492. { bitpacked record? }
  1493. is_packed:=is_packed_record_or_object(def);
  1494. if (is_packed) then
  1495. { packedbitsize will be set separately for each field }
  1496. initbitpackval(bp,0);
  1497. { normal record }
  1498. consume(_LKLAMMER);
  1499. recoffset:=0;
  1500. sorg:='';
  1501. symidx:=0;
  1502. symlist:=def.symtable.SymList;
  1503. srsym:=get_next_varsym(def,symlist,symidx);
  1504. recsym := nil;
  1505. startoffset:=curoffset;
  1506. while token<>_RKLAMMER do
  1507. begin
  1508. s:=pattern;
  1509. sorg:=orgpattern;
  1510. consume(_ID);
  1511. consume(_COLON);
  1512. error := false;
  1513. recsym := tsym(def.symtable.Find(s));
  1514. if not assigned(recsym) then
  1515. begin
  1516. Message1(sym_e_illegal_field,sorg);
  1517. error := true;
  1518. end;
  1519. if (not error) and
  1520. (not assigned(srsym) or
  1521. (s <> srsym.name)) then
  1522. { possible variant record (JM) }
  1523. begin
  1524. { All parts of a variant start at the same offset }
  1525. { Also allow jumping from one variant part to another, }
  1526. { as long as the offsets match }
  1527. if (assigned(srsym) and
  1528. (tfieldvarsym(recsym).fieldoffset = tfieldvarsym(srsym).fieldoffset)) or
  1529. { srsym is not assigned after parsing w2 in the }
  1530. { typed const in the next example: }
  1531. { type tr = record case byte of }
  1532. { 1: (l1,l2: dword); }
  1533. { 2: (w1,w2: word); }
  1534. { end; }
  1535. { const r: tr = (w1:1;w2:1;l2:5); }
  1536. (tfieldvarsym(recsym).fieldoffset = recoffset) then
  1537. begin
  1538. srsym:=recsym;
  1539. { symidx should contain the next symbol id to search }
  1540. symidx:=SymList.indexof(srsym)+1;
  1541. end
  1542. { going backwards isn't allowed in any mode }
  1543. else if (tfieldvarsym(recsym).fieldoffset<recoffset) then
  1544. begin
  1545. Message(parser_e_invalid_record_const);
  1546. error := true;
  1547. end
  1548. { Delphi allows you to skip fields }
  1549. else if (m_delphi in current_settings.modeswitches) then
  1550. begin
  1551. Message1(parser_w_skipped_fields_before,sorg);
  1552. srsym := recsym;
  1553. end
  1554. { FPC and TP don't }
  1555. else
  1556. begin
  1557. Message1(parser_e_skipped_fields_before,sorg);
  1558. error := true;
  1559. end;
  1560. end;
  1561. if error then
  1562. consume_all_until(_SEMICOLON)
  1563. else
  1564. begin
  1565. { if needed fill (alignment) }
  1566. if tfieldvarsym(srsym).fieldoffset>recoffset then
  1567. begin
  1568. if not(is_packed) then
  1569. fillbytes:=0
  1570. else
  1571. begin
  1572. flush_packed_value(bp);
  1573. { curoffset is now aligned to the next byte }
  1574. recoffset:=align(recoffset,8);
  1575. { offsets are in bits in this case }
  1576. fillbytes:=(tfieldvarsym(srsym).fieldoffset-recoffset) div 8;
  1577. end;
  1578. for i:=1 to fillbytes do
  1579. ftcb.emit_tai(Tai_const.Create_8bit(0),u8inttype)
  1580. end;
  1581. { new position }
  1582. recoffset:=tfieldvarsym(srsym).fieldoffset;
  1583. if not(is_packed) then
  1584. inc(recoffset,tfieldvarsym(srsym).vardef.size)
  1585. else
  1586. inc(recoffset,tfieldvarsym(srsym).vardef.packedbitsize);
  1587. { read the data }
  1588. ftcb.next_field:=tfieldvarsym(srsym);
  1589. if not(is_packed) or
  1590. { only orddefs and enumdefs are bitpacked, as in gcc/gpc }
  1591. not(tfieldvarsym(srsym).vardef.typ in [orddef,enumdef]) then
  1592. begin
  1593. if is_packed then
  1594. begin
  1595. flush_packed_value(bp);
  1596. recoffset:=align(recoffset,8);
  1597. end;
  1598. curoffset:=startoffset+tfieldvarsym(srsym).fieldoffset;
  1599. read_typed_const_data(tfieldvarsym(srsym).vardef);
  1600. end
  1601. else
  1602. begin
  1603. bp.packedbitsize:=tfieldvarsym(srsym).vardef.packedbitsize;
  1604. parse_single_packed_const(tfieldvarsym(srsym).vardef,bp);
  1605. end;
  1606. { keep previous field for checking whether whole }
  1607. { record was initialized (JM) }
  1608. recsym := srsym;
  1609. { goto next field }
  1610. srsym:=get_next_varsym(def,SymList,symidx);
  1611. if token=_SEMICOLON then
  1612. consume(_SEMICOLON)
  1613. else if (token=_COMMA) and (m_mac in current_settings.modeswitches) then
  1614. consume(_COMMA)
  1615. else
  1616. break;
  1617. end;
  1618. end;
  1619. curoffset:=startoffset;
  1620. { are there any fields left, but don't complain if there only
  1621. come other variant parts after the last initialized field }
  1622. if assigned(srsym) and
  1623. (
  1624. (recsym=nil) or
  1625. (tfieldvarsym(srsym).fieldoffset > tfieldvarsym(recsym).fieldoffset)
  1626. ) then
  1627. Message1(parser_w_skipped_fields_after,sorg);
  1628. if not error then
  1629. begin
  1630. if not(is_packed) then
  1631. fillbytes:=0
  1632. else
  1633. begin
  1634. flush_packed_value(bp);
  1635. recoffset:=align(recoffset,8);
  1636. fillbytes:=def.size-(recoffset div 8);
  1637. end;
  1638. for i:=1 to fillbytes do
  1639. ftcb.emit_tai(Tai_const.Create_8bit(0),u8inttype);
  1640. end;
  1641. ftcb.maybe_end_aggregate(def);
  1642. consume(_RKLAMMER);
  1643. end;
  1644. procedure tasmlisttypedconstbuilder.parse_objectdef(def:tobjectdef);
  1645. var
  1646. n : tnode;
  1647. obj : tobjectdef;
  1648. srsym : tsym;
  1649. st : tsymtable;
  1650. objoffset : {$ifdef CPU8BITALU}smallint{$else}aint{$endif};
  1651. s,sorg : TIDString;
  1652. vmtwritten : boolean;
  1653. startoffset : {$ifdef CPU8BITALU}smallint{$else}aint{$endif};
  1654. begin
  1655. { no support for packed object }
  1656. if is_packed_record_or_object(def) then
  1657. begin
  1658. Message(type_e_no_const_packed_record);
  1659. exit;
  1660. end;
  1661. { only allow nil for implicit pointer object types }
  1662. if is_implicit_pointer_object_type(def) then
  1663. begin
  1664. n:=comp_expr([ef_accept_equal]);
  1665. if n.nodetype<>niln then
  1666. begin
  1667. Message(parser_e_type_const_not_possible);
  1668. consume_all_until(_SEMICOLON);
  1669. end
  1670. else
  1671. ftcb.emit_tai(Tai_const.Create_sym(nil),def);
  1672. n.free;
  1673. exit;
  1674. end;
  1675. { for objects we allow it only if it doesn't contain a vmt }
  1676. if (oo_has_vmt in def.objectoptions) and
  1677. (m_fpc in current_settings.modeswitches) then
  1678. begin
  1679. Message(parser_e_type_object_constants);
  1680. exit;
  1681. end;
  1682. ftcb.maybe_begin_aggregate(def);
  1683. consume(_LKLAMMER);
  1684. startoffset:=curoffset;
  1685. objoffset:=0;
  1686. vmtwritten:=false;
  1687. while token<>_RKLAMMER do
  1688. begin
  1689. s:=pattern;
  1690. sorg:=orgpattern;
  1691. consume(_ID);
  1692. consume(_COLON);
  1693. srsym:=nil;
  1694. obj:=tobjectdef(def);
  1695. st:=obj.symtable;
  1696. while (srsym=nil) and assigned(st) do
  1697. begin
  1698. srsym:=tsym(st.Find(s));
  1699. if assigned(obj) then
  1700. obj:=obj.childof;
  1701. if assigned(obj) then
  1702. st:=obj.symtable
  1703. else
  1704. st:=nil;
  1705. end;
  1706. if (srsym=nil) or
  1707. (srsym.typ<>fieldvarsym) then
  1708. begin
  1709. if (srsym=nil) then
  1710. Message1(sym_e_id_not_found,sorg)
  1711. else
  1712. Message1(sym_e_illegal_field,sorg);
  1713. consume_all_until(_RKLAMMER);
  1714. break;
  1715. end
  1716. else
  1717. with tfieldvarsym(srsym) do
  1718. begin
  1719. { check position }
  1720. if fieldoffset<objoffset then
  1721. message(parser_e_invalid_record_const);
  1722. { check in VMT needs to be added for TP mode }
  1723. if not(vmtwritten) and
  1724. not(m_fpc in current_settings.modeswitches) and
  1725. (oo_has_vmt in def.objectoptions) and
  1726. (def.vmt_offset<fieldoffset) then
  1727. begin
  1728. ftcb.next_field:=tfieldvarsym(def.vmt_field);
  1729. ftcb.emit_tai(tai_const.createname(def.vmt_mangledname,AT_DATA,0),tfieldvarsym(def.vmt_field).vardef);
  1730. objoffset:=def.vmt_offset+tfieldvarsym(def.vmt_field).vardef.size;
  1731. vmtwritten:=true;
  1732. end;
  1733. ftcb.next_field:=tfieldvarsym(srsym);
  1734. { new position }
  1735. objoffset:=fieldoffset+vardef.size;
  1736. { read the data }
  1737. curoffset:=startoffset+fieldoffset;
  1738. read_typed_const_data(vardef);
  1739. if not try_to_consume(_SEMICOLON) then
  1740. break;
  1741. end;
  1742. end;
  1743. curoffset:=startoffset;
  1744. { add VMT pointer if we stopped writing fields before the VMT was
  1745. written }
  1746. if not(m_fpc in current_settings.modeswitches) and
  1747. (oo_has_vmt in def.objectoptions) and
  1748. (def.vmt_offset>=objoffset) then
  1749. begin
  1750. ftcb.next_field:=tfieldvarsym(def.vmt_field);
  1751. ftcb.emit_tai(tai_const.createname(def.vmt_mangledname,AT_DATA,0),tfieldvarsym(def.vmt_field).vardef);
  1752. objoffset:=def.vmt_offset+tfieldvarsym(def.vmt_field).vardef.size;
  1753. end;
  1754. ftcb.maybe_end_aggregate(def);
  1755. consume(_RKLAMMER);
  1756. end;
  1757. procedure tasmlisttypedconstbuilder.parse_into_asmlist;
  1758. begin
  1759. read_typed_const_data(tcsym.vardef);
  1760. end;
  1761. { tnodetreetypedconstbuilder }
  1762. procedure tnodetreetypedconstbuilder.parse_arraydef(def: tarraydef);
  1763. var
  1764. n : tnode;
  1765. i : longint;
  1766. orgbase: tnode;
  1767. begin
  1768. { dynamic array nil }
  1769. if is_dynamic_array(def) then
  1770. begin
  1771. { Only allow nil initialization }
  1772. consume(_NIL);
  1773. addstatement(statmnt,cassignmentnode.create_internal(basenode,cnilnode.create));
  1774. basenode:=nil;
  1775. end
  1776. { array const between brackets }
  1777. else if try_to_consume(_LKLAMMER) then
  1778. begin
  1779. orgbase:=basenode;
  1780. for i:=def.lowrange to def.highrange-1 do
  1781. begin
  1782. basenode:=cvecnode.create(orgbase.getcopy,ctypeconvnode.create_explicit(genintconstnode(i),tarraydef(def).rangedef));
  1783. read_typed_const_data(def.elementdef);
  1784. if token=_RKLAMMER then
  1785. begin
  1786. Message1(parser_e_more_array_elements_expected,tostr(def.highrange-i));
  1787. consume(_RKLAMMER);
  1788. exit;
  1789. end
  1790. else
  1791. consume(_COMMA);
  1792. end;
  1793. basenode:=cvecnode.create(orgbase,ctypeconvnode.create_explicit(genintconstnode(def.highrange),tarraydef(def).rangedef));
  1794. read_typed_const_data(def.elementdef);
  1795. consume(_RKLAMMER);
  1796. end
  1797. { if array of char then we allow also a string }
  1798. else if is_anychar(def.elementdef) then
  1799. begin
  1800. n:=comp_expr([ef_accept_equal]);
  1801. addstatement(statmnt,cassignmentnode.create_internal(basenode,n));
  1802. basenode:=nil;
  1803. end
  1804. else
  1805. begin
  1806. { we want the ( }
  1807. consume(_LKLAMMER);
  1808. end;
  1809. end;
  1810. procedure tnodetreetypedconstbuilder.parse_procvardef(def: tprocvardef);
  1811. begin
  1812. addstatement(statmnt,cassignmentnode.create_internal(basenode,comp_expr([ef_accept_equal])));
  1813. basenode:=nil;
  1814. end;
  1815. procedure tnodetreetypedconstbuilder.parse_recorddef(def: trecorddef);
  1816. var
  1817. n,n2 : tnode;
  1818. SymList:TFPHashObjectList;
  1819. orgbasenode : tnode;
  1820. symidx : longint;
  1821. recsym,
  1822. srsym : tsym;
  1823. sorg,s : TIDString;
  1824. recoffset : {$ifdef CPU8BITALU}smallint{$else}aint{$endif};
  1825. error,
  1826. is_packed: boolean;
  1827. procedure handle_stringconstn;
  1828. begin
  1829. addstatement(statmnt,cassignmentnode.create_internal(basenode,n));
  1830. basenode:=nil;
  1831. n:=nil;
  1832. end;
  1833. begin
  1834. { GUID }
  1835. if (def=rec_tguid) and (token=_ID) then
  1836. begin
  1837. n:=comp_expr([ef_accept_equal]);
  1838. if n.nodetype=stringconstn then
  1839. handle_stringconstn
  1840. else
  1841. begin
  1842. inserttypeconv(n,rec_tguid);
  1843. if n.nodetype=guidconstn then
  1844. begin
  1845. n2:=cstringconstnode.createstr(guid2string(tguidconstnode(n).value));
  1846. n.free;
  1847. n:=n2;
  1848. handle_stringconstn;
  1849. end
  1850. else
  1851. Message(parser_e_illegal_expression);
  1852. end;
  1853. n.free;
  1854. exit;
  1855. end;
  1856. if (def=rec_tguid) and ((token=_CSTRING) or (token=_CCHAR)) then
  1857. begin
  1858. n:=comp_expr([ef_accept_equal]);
  1859. inserttypeconv(n,cshortstringtype);
  1860. if n.nodetype=stringconstn then
  1861. handle_stringconstn
  1862. else
  1863. Message(parser_e_illegal_expression);
  1864. n.free;
  1865. exit;
  1866. end;
  1867. { bitpacked record? }
  1868. is_packed:=is_packed_record_or_object(def);
  1869. { normal record }
  1870. consume(_LKLAMMER);
  1871. recoffset:=0;
  1872. sorg:='';
  1873. symidx:=0;
  1874. symlist:=def.symtable.SymList;
  1875. srsym:=get_next_varsym(def,symlist,symidx);
  1876. recsym := nil;
  1877. orgbasenode:=basenode;
  1878. basenode:=nil;
  1879. while token<>_RKLAMMER do
  1880. begin
  1881. s:=pattern;
  1882. sorg:=orgpattern;
  1883. consume(_ID);
  1884. consume(_COLON);
  1885. error := false;
  1886. recsym := tsym(def.symtable.Find(s));
  1887. if not assigned(recsym) then
  1888. begin
  1889. Message1(sym_e_illegal_field,sorg);
  1890. error := true;
  1891. end;
  1892. if (not error) and
  1893. (not assigned(srsym) or
  1894. (s <> srsym.name)) then
  1895. { possible variant record (JM) }
  1896. begin
  1897. { All parts of a variant start at the same offset }
  1898. { Also allow jumping from one variant part to another, }
  1899. { as long as the offsets match }
  1900. if (assigned(srsym) and
  1901. (tfieldvarsym(recsym).fieldoffset = tfieldvarsym(srsym).fieldoffset)) or
  1902. { srsym is not assigned after parsing w2 in the }
  1903. { typed const in the next example: }
  1904. { type tr = record case byte of }
  1905. { 1: (l1,l2: dword); }
  1906. { 2: (w1,w2: word); }
  1907. { end; }
  1908. { const r: tr = (w1:1;w2:1;l2:5); }
  1909. (tfieldvarsym(recsym).fieldoffset = recoffset) then
  1910. begin
  1911. srsym:=recsym;
  1912. { symidx should contain the next symbol id to search }
  1913. symidx:=SymList.indexof(srsym)+1;
  1914. end
  1915. { going backwards isn't allowed in any mode }
  1916. else if (tfieldvarsym(recsym).fieldoffset<recoffset) then
  1917. begin
  1918. Message(parser_e_invalid_record_const);
  1919. error := true;
  1920. end
  1921. { Delphi allows you to skip fields }
  1922. else if (m_delphi in current_settings.modeswitches) then
  1923. begin
  1924. Message1(parser_w_skipped_fields_before,sorg);
  1925. srsym := recsym;
  1926. end
  1927. { FPC and TP don't }
  1928. else
  1929. begin
  1930. Message1(parser_e_skipped_fields_before,sorg);
  1931. error := true;
  1932. end;
  1933. end;
  1934. if error then
  1935. consume_all_until(_SEMICOLON)
  1936. else
  1937. begin
  1938. { skipping fill bytes happens automatically, since we only
  1939. initialize the defined fields }
  1940. { new position }
  1941. recoffset:=tfieldvarsym(srsym).fieldoffset;
  1942. if not(is_packed) then
  1943. inc(recoffset,tfieldvarsym(srsym).vardef.size)
  1944. else
  1945. inc(recoffset,tfieldvarsym(srsym).vardef.packedbitsize);
  1946. { read the data }
  1947. if is_packed and
  1948. { only orddefs and enumdefs are bitpacked, as in gcc/gpc }
  1949. not(tfieldvarsym(srsym).vardef.typ in [orddef,enumdef]) then
  1950. recoffset:=align(recoffset,8);
  1951. basenode:=csubscriptnode.create(srsym,orgbasenode.getcopy);
  1952. read_typed_const_data(tfieldvarsym(srsym).vardef);
  1953. { keep previous field for checking whether whole }
  1954. { record was initialized (JM) }
  1955. recsym := srsym;
  1956. { goto next field }
  1957. srsym:=get_next_varsym(def,SymList,symidx);
  1958. if token=_SEMICOLON then
  1959. consume(_SEMICOLON)
  1960. else if (token=_COMMA) and (m_mac in current_settings.modeswitches) then
  1961. consume(_COMMA)
  1962. else
  1963. break;
  1964. end;
  1965. end;
  1966. { are there any fields left, but don't complain if there only
  1967. come other variant parts after the last initialized field }
  1968. if assigned(srsym) and
  1969. (
  1970. (recsym=nil) or
  1971. (tfieldvarsym(srsym).fieldoffset > tfieldvarsym(recsym).fieldoffset)
  1972. ) then
  1973. Message1(parser_w_skipped_fields_after,sorg);
  1974. orgbasenode.free;
  1975. basenode:=nil;
  1976. consume(_RKLAMMER);
  1977. end;
  1978. procedure tnodetreetypedconstbuilder.parse_objectdef(def: tobjectdef);
  1979. var
  1980. n,
  1981. orgbasenode : tnode;
  1982. obj : tobjectdef;
  1983. srsym : tsym;
  1984. st : tsymtable;
  1985. objoffset : {$ifdef CPU8BITALU}smallint{$else}aint{$endif};
  1986. s,sorg : TIDString;
  1987. begin
  1988. { no support for packed object }
  1989. if is_packed_record_or_object(def) then
  1990. begin
  1991. Message(type_e_no_const_packed_record);
  1992. exit;
  1993. end;
  1994. { only allow nil for implicit pointer object types }
  1995. if is_implicit_pointer_object_type(def) then
  1996. begin
  1997. n:=comp_expr([ef_accept_equal]);
  1998. if n.nodetype<>niln then
  1999. begin
  2000. Message(parser_e_type_const_not_possible);
  2001. consume_all_until(_SEMICOLON);
  2002. end
  2003. else
  2004. begin
  2005. addstatement(statmnt,cassignmentnode.create_internal(basenode,n));
  2006. n:=nil;
  2007. basenode:=nil;
  2008. end;
  2009. n.free;
  2010. exit;
  2011. end;
  2012. { for objects we allow it only if it doesn't contain a vmt }
  2013. if (oo_has_vmt in def.objectoptions) and
  2014. (m_fpc in current_settings.modeswitches) then
  2015. begin
  2016. Message(parser_e_type_object_constants);
  2017. exit;
  2018. end;
  2019. consume(_LKLAMMER);
  2020. objoffset:=0;
  2021. orgbasenode:=basenode;
  2022. basenode:=nil;
  2023. while token<>_RKLAMMER do
  2024. begin
  2025. s:=pattern;
  2026. sorg:=orgpattern;
  2027. consume(_ID);
  2028. consume(_COLON);
  2029. srsym:=nil;
  2030. obj:=tobjectdef(def);
  2031. st:=obj.symtable;
  2032. while (srsym=nil) and assigned(st) do
  2033. begin
  2034. srsym:=tsym(st.Find(s));
  2035. if assigned(obj) then
  2036. obj:=obj.childof;
  2037. if assigned(obj) then
  2038. st:=obj.symtable
  2039. else
  2040. st:=nil;
  2041. end;
  2042. if (srsym=nil) or
  2043. (srsym.typ<>fieldvarsym) then
  2044. begin
  2045. if (srsym=nil) then
  2046. Message1(sym_e_id_not_found,sorg)
  2047. else
  2048. Message1(sym_e_illegal_field,sorg);
  2049. consume_all_until(_RKLAMMER);
  2050. break;
  2051. end
  2052. else
  2053. with tfieldvarsym(srsym) do
  2054. begin
  2055. { check position }
  2056. if fieldoffset<objoffset then
  2057. message(parser_e_invalid_record_const);
  2058. { new position }
  2059. objoffset:=fieldoffset+vardef.size;
  2060. { read the data }
  2061. basenode:=csubscriptnode.create(srsym,orgbasenode.getcopy);
  2062. read_typed_const_data(vardef);
  2063. if not try_to_consume(_SEMICOLON) then
  2064. break;
  2065. end;
  2066. end;
  2067. consume(_RKLAMMER);
  2068. end;
  2069. procedure tnodetreetypedconstbuilder.tc_emit_orddef(def: torddef; var node: tnode);
  2070. begin
  2071. addstatement(statmnt,cassignmentnode.create_internal(basenode,node));
  2072. basenode:=nil;
  2073. node:=nil;
  2074. end;
  2075. procedure tnodetreetypedconstbuilder.tc_emit_floatdef(def: tfloatdef; var node: tnode);
  2076. begin
  2077. addstatement(statmnt,cassignmentnode.create_internal(basenode,node));
  2078. basenode:=nil;
  2079. node:=nil;
  2080. end;
  2081. procedure tnodetreetypedconstbuilder.tc_emit_classrefdef(def: tclassrefdef; var node: tnode);
  2082. begin
  2083. addstatement(statmnt,cassignmentnode.create_internal(basenode,node));
  2084. basenode:=nil;
  2085. node:=nil;
  2086. end;
  2087. procedure tnodetreetypedconstbuilder.tc_emit_pointerdef(def: tpointerdef; var node: tnode);
  2088. begin
  2089. addstatement(statmnt,cassignmentnode.create_internal(basenode,node));
  2090. basenode:=nil;
  2091. node:=nil;
  2092. end;
  2093. procedure tnodetreetypedconstbuilder.tc_emit_setdef(def: tsetdef; var node: tnode);
  2094. begin
  2095. addstatement(statmnt,cassignmentnode.create_internal(basenode,node));
  2096. basenode:=nil;
  2097. node:=nil;
  2098. end;
  2099. procedure tnodetreetypedconstbuilder.tc_emit_enumdef(def: tenumdef; var node: tnode);
  2100. begin
  2101. addstatement(statmnt,cassignmentnode.create_internal(basenode,node));
  2102. basenode:=nil;
  2103. node:=nil;
  2104. end;
  2105. procedure tnodetreetypedconstbuilder.tc_emit_stringdef(def: tstringdef; var node: tnode);
  2106. begin
  2107. addstatement(statmnt,cassignmentnode.create_internal(basenode,node));
  2108. basenode:=nil;
  2109. node:=nil;
  2110. end;
  2111. constructor tnodetreetypedconstbuilder.create(sym: tstaticvarsym; previnit: tnode);
  2112. begin
  2113. inherited create(sym);
  2114. basenode:=cloadnode.create(sym,sym.owner);
  2115. resultblock:=internalstatements(statmnt);
  2116. if assigned(previnit) then
  2117. addstatement(statmnt,previnit);
  2118. end;
  2119. destructor tnodetreetypedconstbuilder.destroy;
  2120. begin
  2121. freeandnil(basenode);
  2122. freeandnil(resultblock);
  2123. inherited destroy;
  2124. end;
  2125. function tnodetreetypedconstbuilder.parse_into_nodetree: tnode;
  2126. begin
  2127. read_typed_const_data(tcsym.vardef);
  2128. result:=self.resultblock;
  2129. self.resultblock:=nil;
  2130. end;
  2131. begin
  2132. { default to asmlist version, best for most targets }
  2133. ctypedconstbuilder:=tasmlisttypedconstbuilder;
  2134. end.