ngtcon.pas 88 KB

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