ncgld.pas 49 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl
  4. Generate assembler for nodes that handle loads and assignments which
  5. are the same for all (most) processors
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2 of the License, or
  9. (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program; if not, write to the Free Software
  16. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. ****************************************************************************
  18. }
  19. unit ncgld;
  20. {$i fpcdefs.inc}
  21. interface
  22. uses
  23. node,nld;
  24. type
  25. tcgloadnode = class(tloadnode)
  26. procedure pass_2;override;
  27. end;
  28. tcgassignmentnode = class(tassignmentnode)
  29. procedure pass_2;override;
  30. end;
  31. tcgarrayconstructornode = class(tarrayconstructornode)
  32. procedure pass_2;override;
  33. end;
  34. implementation
  35. uses
  36. systems,
  37. verbose,globtype,globals,
  38. symconst,symtype,symdef,symsym,symtable,defutil,paramgr,
  39. ncnv,ncon,nmem,
  40. aasmbase,aasmtai,aasmcpu,regvars,
  41. cginfo,cgbase,pass_2,
  42. cpubase,cpuinfo,cpupara,
  43. tgobj,ncgutil,cgobj,rgobj,rgcpu;
  44. {*****************************************************************************
  45. SecondLoad
  46. *****************************************************************************}
  47. procedure tcgloadnode.pass_2;
  48. var
  49. r,hregister : tregister;
  50. supreg:Tsuperregister;
  51. symtabletype : tsymtabletype;
  52. i : longint;
  53. href : treference;
  54. newsize : tcgsize;
  55. pushed : tpushedsavedint;
  56. dorelocatelab,
  57. norelocatelab : tasmlabel;
  58. begin
  59. { we don't know the size of all arrays }
  60. newsize:=def_cgsize(resulttype.def);
  61. location_reset(location,LOC_REFERENCE,newsize);
  62. case symtableentry.typ of
  63. absolutesym :
  64. begin
  65. { this is only for toasm and toaddr }
  66. if (tabsolutesym(symtableentry).abstyp=toaddr) then
  67. begin
  68. {$ifdef i386}
  69. if tabsolutesym(symtableentry).absseg then
  70. location.reference.segment.enum:=R_FS;
  71. {$endif i386}
  72. location.reference.offset:=tabsolutesym(symtableentry).address;
  73. end
  74. else
  75. location.reference.symbol:=objectlibrary.newasmsymboldata(tabsolutesym(symtableentry).mangledname);
  76. end;
  77. constsym:
  78. begin
  79. if tconstsym(symtableentry).consttyp=constresourcestring then
  80. begin
  81. location_reset(location,LOC_CREFERENCE,OS_ADDR);
  82. location.reference.symbol:=objectlibrary.newasmsymboldata(tconstsym(symtableentry).owner.name^+'_RESOURCESTRINGLIST');
  83. location.reference.offset:=tconstsym(symtableentry).resstrindex*16+8;
  84. end
  85. else
  86. internalerror(22798);
  87. end;
  88. varsym :
  89. begin
  90. if (tvarsym(symtableentry).varspez=vs_const) then
  91. location_reset(location,LOC_CREFERENCE,newsize);
  92. symtabletype:=symtable.symtabletype;
  93. hregister.enum:=R_NO;
  94. { C variable }
  95. if (vo_is_C_var in tvarsym(symtableentry).varoptions) then
  96. begin
  97. location.reference.symbol:=objectlibrary.newasmsymboldata(tvarsym(symtableentry).mangledname);
  98. end
  99. { DLL variable }
  100. else if (vo_is_dll_var in tvarsym(symtableentry).varoptions) then
  101. begin
  102. hregister:=rg.getaddressregister(exprasmlist);
  103. location.reference.symbol:=objectlibrary.newasmsymboldata(tvarsym(symtableentry).mangledname);
  104. cg.a_load_ref_reg(exprasmlist,OS_ADDR,location.reference,hregister);
  105. reference_reset_base(location.reference,hregister,0);
  106. end
  107. { external variable }
  108. else if (vo_is_external in tvarsym(symtableentry).varoptions) then
  109. begin
  110. location.reference.symbol:=objectlibrary.newasmsymboldata(tvarsym(symtableentry).mangledname);
  111. end
  112. { thread variable }
  113. else if (vo_is_thread_var in tvarsym(symtableentry).varoptions) then
  114. begin
  115. objectlibrary.getlabel(dorelocatelab);
  116. objectlibrary.getlabel(norelocatelab);
  117. { we've to allocate the register before we save the used registers }
  118. hregister:=rg.getaddressregister(exprasmlist);
  119. reference_reset_symbol(href,objectlibrary.newasmsymboldata('FPC_THREADVAR_RELOCATE'),0);
  120. cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,hregister);
  121. cg.a_cmp_const_reg_label(exprasmlist,OS_ADDR,OC_NE,0,hregister,dorelocatelab);
  122. { no relocation needed, load the address of the variable only, the
  123. layout of a threadvar is (4 bytes pointer):
  124. 0 - Threadvar index
  125. 4 - Threadvar value in single threading }
  126. reference_reset_symbol(href,objectlibrary.newasmsymboldata(tvarsym(symtableentry).mangledname),POINTER_SIZE);
  127. cg.a_loadaddr_ref_reg(exprasmlist,href,hregister);
  128. cg.a_jmp_always(exprasmlist,norelocatelab);
  129. cg.a_label(exprasmlist,dorelocatelab);
  130. if hregister.enum<>R_INTREGISTER then
  131. internalerror(200301171);
  132. { don't save the allocated register else the result will be destroyed later }
  133. rg.saveusedintregisters(exprasmlist,pushed,[RS_ACCUMULATOR]-[hregister.number shr 8]);
  134. reference_reset_symbol(href,objectlibrary.newasmsymboldata(tvarsym(symtableentry).mangledname),0);
  135. cg.a_param_ref(exprasmlist,OS_ADDR,href,paramanager.getintparaloc(1));
  136. { the called procedure isn't allowed to change }
  137. { any register except EAX }
  138. cg.a_call_reg(exprasmlist,hregister);
  139. r.enum:=R_INTREGISTER;
  140. r.number:=NR_ACCUMULATOR;
  141. cg.a_load_reg_reg(exprasmlist,OS_INT,OS_ADDR,r,hregister);
  142. rg.restoreusedintregisters(exprasmlist,pushed);
  143. cg.a_label(exprasmlist,norelocatelab);
  144. location.reference.base:=hregister;
  145. end
  146. { normal variable }
  147. else
  148. begin
  149. { in case it is a register variable: }
  150. if tvarsym(symtableentry).reg.enum<>R_NO then
  151. begin
  152. if tvarsym(symtableentry).reg.enum in fpuregs then
  153. begin
  154. location_reset(location,LOC_CFPUREGISTER,def_cgsize(resulttype.def));
  155. location.register:=tvarsym(symtableentry).reg;
  156. end
  157. else if Tvarsym(symtableentry).reg.enum=R_INTREGISTER then
  158. begin
  159. supreg:=Tvarsym(symtableentry).reg.number shr 8;
  160. if (supreg in general_superregisters) and
  161. not (supreg in rg.regvar_loaded_int) then
  162. load_regvar(exprasmlist,tvarsym(symtableentry));
  163. location_reset(location,LOC_CREGISTER,cg.reg_cgsize(tvarsym(symtableentry).reg));
  164. location.register:=tvarsym(symtableentry).reg;
  165. exclude(rg.unusedregsint,supreg);
  166. end
  167. else
  168. internalerror(200301172);
  169. end
  170. else
  171. begin
  172. case symtabletype of
  173. localsymtable,
  174. parasymtable,
  175. inlinelocalsymtable,
  176. inlineparasymtable :
  177. begin
  178. location.reference.base:=current_procinfo.framepointer;
  179. if (symtabletype in [inlinelocalsymtable,
  180. localsymtable])
  181. then
  182. location.reference.offset:=
  183. tvarsym(symtableentry).address+tg.direction*symtable.address_fixup
  184. else
  185. location.reference.offset:=
  186. tvarsym(symtableentry).address+symtable.address_fixup;
  187. {$ifndef powerpc}
  188. if (symtabletype in [localsymtable,inlinelocalsymtable]) then
  189. begin
  190. if use_esp_stackframe then
  191. dec(location.reference.offset,
  192. tvarsym(symtableentry).getvaluesize)
  193. else
  194. location.reference.offset:=-location.reference.offset;
  195. end;
  196. {$endif powerpc}
  197. if (current_procdef.parast.symtablelevel>symtable.symtablelevel) then
  198. begin
  199. hregister:=rg.getaddressregister(exprasmlist);
  200. { make a reference }
  201. reference_reset_base(href,current_procinfo.framepointer,current_procinfo.framepointer_offset);
  202. cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,hregister);
  203. { walk parents }
  204. i:=current_procdef.parast.symtablelevel-1;
  205. while (i>symtable.symtablelevel) do
  206. begin
  207. { make a reference }
  208. reference_reset_base(href,hregister,target_info.first_parm_offset);
  209. cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,hregister);
  210. dec(i);
  211. end;
  212. location.reference.base:=hregister;
  213. end;
  214. end;
  215. globalsymtable,
  216. staticsymtable :
  217. begin
  218. location.reference.symbol:=objectlibrary.newasmsymboldata(tvarsym(symtableentry).mangledname);
  219. end;
  220. stt_exceptsymtable:
  221. begin
  222. location.reference.base:=current_procinfo.framepointer;
  223. location.reference.offset:=tvarsym(symtableentry).address;
  224. end;
  225. else
  226. internalerror(200305102);
  227. end;
  228. end;
  229. end;
  230. { handle call by reference variables, ignore the reference
  231. when we need to load the self pointer for objects }
  232. if (symtabletype in [parasymtable,inlineparasymtable]) and
  233. not(nf_load_self_pointer in flags) and
  234. (
  235. (tvarsym(symtableentry).varspez in [vs_var,vs_out]) or
  236. paramanager.push_addr_param(tvarsym(symtableentry).vartype.def,tprocdef(symtable.defowner).proccalloption)
  237. ) then
  238. begin
  239. if hregister.enum=R_NO then
  240. hregister:=rg.getaddressregister(exprasmlist);
  241. { we need to load only an address }
  242. location.size:=OS_ADDR;
  243. cg.a_load_loc_reg(exprasmlist,location,hregister);
  244. if tvarsym(symtableentry).varspez=vs_const then
  245. location_reset(location,LOC_CREFERENCE,newsize)
  246. else
  247. location_reset(location,LOC_REFERENCE,newsize);
  248. location.reference.base:=hregister;
  249. end;
  250. end;
  251. procsym:
  252. begin
  253. if assigned(left) then
  254. begin
  255. {
  256. THIS IS A TERRIBLE HACK!!!!!! WHICH WILL NOT WORK
  257. ON 64-BIT SYSTEMS: SINCE PROCSYM FOR METHODS
  258. CONSISTS OF TWO OS_ADDR, so you cannot set it
  259. to OS_64 - how to solve?? Carl
  260. }
  261. if (sizeof(aword) = 4) then
  262. location_reset(location,LOC_CREFERENCE,OS_64)
  263. else
  264. internalerror(20020520);
  265. tg.GetTemp(exprasmlist,2*POINTER_SIZE,tt_normal,location.reference);
  266. secondpass(left);
  267. { load class instance address }
  268. case left.location.loc of
  269. LOC_CREGISTER,
  270. LOC_REGISTER:
  271. begin
  272. { this is not possible for objects }
  273. if is_object(left.resulttype.def) then
  274. internalerror(200304234);
  275. hregister:=left.location.register;
  276. end;
  277. LOC_CREFERENCE,
  278. LOC_REFERENCE:
  279. begin
  280. hregister:=rg.getaddressregister(exprasmlist);
  281. if is_class_or_interface(left.resulttype.def) then
  282. cg.a_load_ref_reg(exprasmlist,OS_ADDR,left.location.reference,hregister)
  283. else
  284. cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,hregister);
  285. location_release(exprasmlist,left.location);
  286. location_freetemp(exprasmlist,left.location);
  287. end;
  288. else
  289. internalerror(26019);
  290. end;
  291. { store the class instance address }
  292. href:=location.reference;
  293. inc(href.offset,POINTER_SIZE);
  294. cg.a_load_reg_ref(exprasmlist,OS_ADDR,hregister,href);
  295. { virtual method ? }
  296. if (po_virtualmethod in procdef.procoptions) then
  297. begin
  298. { load vmt pointer }
  299. reference_reset_base(href,hregister,0);
  300. reference_release(exprasmlist,href);
  301. hregister:=rg.getaddressregister(exprasmlist);
  302. cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,hregister);
  303. reference_reset_base(href,hregister,
  304. procdef._class.vmtmethodoffset(procdef.extnumber));
  305. reference_release(exprasmlist,href);
  306. { load method address }
  307. hregister:=rg.getaddressregister(exprasmlist);
  308. cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,hregister);
  309. { ... and store it }
  310. cg.a_load_reg_ref(exprasmlist,OS_ADDR,hregister,location.reference);
  311. rg.ungetaddressregister(exprasmlist,hregister);
  312. end
  313. else
  314. begin
  315. { we don't use the hregister }
  316. rg.ungetregisterint(exprasmlist,hregister);
  317. { load address of the function }
  318. reference_reset_symbol(href,objectlibrary.newasmsymbol(procdef.mangledname),0);
  319. {$ifdef newra}
  320. hregister:=rg.getaddressregister(exprasmlist);
  321. {$else}
  322. hregister:=cg.get_scratch_reg_address(exprasmlist);
  323. {$endif}
  324. cg.a_loadaddr_ref_reg(exprasmlist,href,hregister);
  325. cg.a_load_reg_ref(exprasmlist,OS_ADDR,hregister,location.reference);
  326. {$ifdef newra}
  327. rg.ungetregisterint(exprasmlist,hregister);
  328. {$else newra}
  329. cg.free_scratch_reg(exprasmlist,hregister);
  330. {$endif}
  331. end;
  332. end
  333. else
  334. begin
  335. {!!!!! Be aware, work on virtual methods too }
  336. location.reference.symbol:=objectlibrary.newasmsymbol(procdef.mangledname);
  337. end;
  338. end;
  339. typedconstsym :
  340. begin
  341. location.reference.symbol:=objectlibrary.newasmsymboldata(ttypedconstsym(symtableentry).mangledname);
  342. end;
  343. else internalerror(4);
  344. end;
  345. end;
  346. {*****************************************************************************
  347. SecondAssignment
  348. *****************************************************************************}
  349. procedure tcgassignmentnode.pass_2;
  350. var
  351. otlabel,hlabel,oflabel : tasmlabel;
  352. fputyp : tfloattype;
  353. href : treference;
  354. old_allow_multi_pass2,
  355. releaseright : boolean;
  356. pushedregs : tmaybesave;
  357. cgsize : tcgsize;
  358. r:Tregister;
  359. begin
  360. location_reset(location,LOC_VOID,OS_NO);
  361. otlabel:=truelabel;
  362. oflabel:=falselabel;
  363. objectlibrary.getlabel(truelabel);
  364. objectlibrary.getlabel(falselabel);
  365. {
  366. in most cases we can process first the right node which contains
  367. the most complex code. But not when the result is in the flags, then
  368. loading the left node afterwards can destroy the flags.
  369. when the right node returns as LOC_JUMP then we will generate
  370. the following code:
  371. rightnode
  372. true:
  373. leftnode
  374. assign 1
  375. false:
  376. leftnode
  377. assign 0
  378. }
  379. { Try to determine which side to calculate first, }
  380. if (right.expectloc<>LOC_FLAGS) and
  381. ((right.expectloc=LOC_JUMP) or
  382. (right.nodetype=calln) or
  383. (right.registers32>=left.registers32)) then
  384. begin
  385. secondpass(right);
  386. { increment source reference counter, this is
  387. useless for string constants}
  388. if (right.resulttype.def.needs_inittable) and
  389. (right.nodetype<>stringconstn) then
  390. cg.g_incrrefcount(exprasmlist,right.resulttype.def,right.location.reference,false);
  391. if codegenerror then
  392. exit;
  393. { We skip the generation of the left node when it's a jump, see
  394. explanation above }
  395. if (right.location.loc<>LOC_JUMP) and
  396. not(nf_concat_string in flags) then
  397. begin
  398. { left can't be never a 64 bit LOC_REGISTER, so the 3. arg }
  399. { can be false }
  400. {$ifndef newra}
  401. maybe_save(exprasmlist,left.registers32,right.location,pushedregs);
  402. {$endif}
  403. secondpass(left);
  404. { decrement destination reference counter }
  405. if (left.resulttype.def.needs_inittable) then
  406. cg.g_decrrefcount(exprasmlist,left.resulttype.def,left.location.reference,false);
  407. {$ifndef newra}
  408. maybe_restore(exprasmlist,right.location,pushedregs);
  409. {$endif newra}
  410. if codegenerror then
  411. exit;
  412. end;
  413. end
  414. else
  415. begin
  416. { calculate left sides }
  417. { don't do it yet if it's a crgister (JM) }
  418. if not(nf_concat_string in flags) then
  419. begin
  420. secondpass(left);
  421. { decrement destination reference counter }
  422. if (left.resulttype.def.needs_inittable) then
  423. cg.g_decrrefcount(exprasmlist,left.resulttype.def,left.location.reference,false);
  424. if codegenerror then
  425. exit;
  426. end;
  427. { left can't be never a 64 bit LOC_REGISTER, so the 3. arg }
  428. { can be false }
  429. {$ifndef newra}
  430. maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
  431. {$endif newra}
  432. secondpass(right);
  433. { increment source reference counter, this is
  434. useless for string constants}
  435. if (right.resulttype.def.needs_inittable) and
  436. (right.nodetype<>stringconstn) then
  437. cg.g_incrrefcount(exprasmlist,right.resulttype.def,right.location.reference,false);
  438. {$ifndef newra}
  439. maybe_restore(exprasmlist,left.location,pushedregs);
  440. {$endif}
  441. if codegenerror then
  442. exit;
  443. end;
  444. releaseright:=true;
  445. { shortstring assignments are handled separately }
  446. if is_shortstring(left.resulttype.def) then
  447. begin
  448. {
  449. we can get here only in the following situations
  450. for the right node:
  451. - empty constant string
  452. - char
  453. }
  454. { empty constant string }
  455. if (right.nodetype=stringconstn) and
  456. (tstringconstnode(right).len=0) then
  457. begin
  458. cg.a_load_const_ref(exprasmlist,OS_8,0,left.location.reference);
  459. end
  460. { char loading }
  461. else if is_char(right.resulttype.def) then
  462. begin
  463. if right.nodetype=ordconstn then
  464. begin
  465. if (target_info.endian = endian_little) then
  466. cg.a_load_const_ref(exprasmlist,OS_16,(tordconstnode(right).value shl 8) or 1,
  467. left.location.reference)
  468. else
  469. cg.a_load_const_ref(exprasmlist,OS_16,tordconstnode(right).value or (1 shl 8),
  470. left.location.reference);
  471. end
  472. else
  473. begin
  474. href:=left.location.reference;
  475. cg.a_load_const_ref(exprasmlist,OS_8,1,href);
  476. inc(href.offset,1);
  477. case right.location.loc of
  478. LOC_REGISTER,
  479. LOC_CREGISTER :
  480. begin
  481. r.enum:=R_INTREGISTER;
  482. r.number:=(right.location.register.number and not $ff) or R_SUBL;
  483. cg.a_load_reg_ref(exprasmlist,OS_8,r,href);
  484. end;
  485. LOC_REFERENCE,
  486. LOC_CREFERENCE :
  487. cg.a_load_ref_ref(exprasmlist,OS_8,right.location.reference,href);
  488. else
  489. internalerror(200205111);
  490. end;
  491. end;
  492. end
  493. else
  494. internalerror(200204249);
  495. end
  496. else
  497. begin
  498. case right.location.loc of
  499. LOC_CONSTANT :
  500. begin
  501. if right.location.size in [OS_64,OS_S64] then
  502. cg64.a_load64_const_loc(exprasmlist,
  503. right.location.valueqword,left.location)
  504. else
  505. cg.a_load_const_loc(exprasmlist,right.location.value,left.location);
  506. end;
  507. LOC_REFERENCE,
  508. LOC_CREFERENCE :
  509. begin
  510. case left.location.loc of
  511. LOC_CREGISTER :
  512. begin
  513. cgsize:=def_cgsize(left.resulttype.def);
  514. if cgsize in [OS_64,OS_S64] then
  515. cg64.a_load64_ref_reg(exprasmlist,
  516. right.location.reference,left.location.register64)
  517. else
  518. cg.a_load_ref_reg(exprasmlist,cgsize,
  519. right.location.reference,left.location.register);
  520. location_release(exprasmlist,right.location);
  521. end;
  522. LOC_CFPUREGISTER :
  523. begin
  524. cg.a_loadfpu_ref_reg(exprasmlist,
  525. def_cgsize(right.resulttype.def),
  526. right.location.reference,
  527. left.location.register);
  528. end;
  529. LOC_REFERENCE,
  530. LOC_CREFERENCE :
  531. begin
  532. cg.g_concatcopy(exprasmlist,right.location.reference,
  533. left.location.reference,left.resulttype.def.size,true,false);
  534. { right.location is already released by concatcopy }
  535. releaseright:=false;
  536. end;
  537. else
  538. internalerror(200203284);
  539. end;
  540. end;
  541. {$ifdef SUPPORT_MMX}
  542. LOC_CMMXREGISTER,
  543. LOC_MMXREGISTER:
  544. begin
  545. if left.location.loc=LOC_CMMXREGISTER then
  546. cg.a_loadmm_reg_reg(exprasmlist,right.location.register,left.location.register)
  547. else
  548. cg.a_loadmm_reg_ref(exprasmlist,right.location.register,left.location.reference);
  549. end;
  550. {$endif SUPPORT_MMX}
  551. LOC_REGISTER,
  552. LOC_CREGISTER :
  553. begin
  554. cgsize:=def_cgsize(left.resulttype.def);
  555. if cgsize in [OS_64,OS_S64] then
  556. cg64.a_load64_reg_loc(exprasmlist,
  557. right.location.register64,left.location)
  558. else
  559. cg.a_load_reg_loc(exprasmlist,right.location.size,right.location.register,left.location);
  560. end;
  561. LOC_FPUREGISTER,LOC_CFPUREGISTER :
  562. begin
  563. if (left.resulttype.def.deftype=floatdef) then
  564. fputyp:=tfloatdef(left.resulttype.def).typ
  565. else
  566. if (right.resulttype.def.deftype=floatdef) then
  567. fputyp:=tfloatdef(right.resulttype.def).typ
  568. else
  569. if (right.nodetype=typeconvn) and
  570. (ttypeconvnode(right).left.resulttype.def.deftype=floatdef) then
  571. fputyp:=tfloatdef(ttypeconvnode(right).left.resulttype.def).typ
  572. else
  573. fputyp:=s32real;
  574. cg.a_loadfpu_reg_loc(exprasmlist,
  575. tfloat2tcgsize[fputyp],
  576. right.location.register,left.location);
  577. end;
  578. LOC_JUMP :
  579. begin
  580. cgsize:=def_cgsize(left.resulttype.def);
  581. objectlibrary.getlabel(hlabel);
  582. { generate the leftnode for the true case, and
  583. release the location }
  584. cg.a_label(exprasmlist,truelabel);
  585. {$ifndef newra}
  586. maybe_save(exprasmlist,left.registers32,right.location,pushedregs);
  587. {$endif newra}
  588. secondpass(left);
  589. {$ifndef newra}
  590. maybe_restore(exprasmlist,right.location,pushedregs);
  591. {$endif newra}
  592. if codegenerror then
  593. exit;
  594. cg.a_load_const_loc(exprasmlist,1,left.location);
  595. location_release(exprasmlist,left.location);
  596. cg.a_jmp_always(exprasmlist,hlabel);
  597. { generate the leftnode for the false case }
  598. cg.a_label(exprasmlist,falselabel);
  599. {$ifndef newra}
  600. maybe_save(exprasmlist,left.registers32,right.location,pushedregs);
  601. {$endif}
  602. old_allow_multi_pass2:=allow_multi_pass2;
  603. allow_multi_pass2:=true;
  604. secondpass(left);
  605. allow_multi_pass2:=old_allow_multi_pass2;
  606. {$ifndef newra}
  607. maybe_restore(exprasmlist,right.location,pushedregs);
  608. {$endif newra}
  609. if codegenerror then
  610. exit;
  611. cg.a_load_const_loc(exprasmlist,0,left.location);
  612. cg.a_label(exprasmlist,hlabel);
  613. end;
  614. {$ifdef cpuflags}
  615. LOC_FLAGS :
  616. begin
  617. {This can be a wordbool or longbool too, no?}
  618. if left.location.loc=LOC_CREGISTER then
  619. cg.g_flags2reg(exprasmlist,def_cgsize(left.resulttype.def),right.location.resflags,left.location.register)
  620. else
  621. begin
  622. if not(left.location.loc = LOC_REFERENCE) then
  623. internalerror(200203273);
  624. cg.g_flags2ref(exprasmlist,def_cgsize(left.resulttype.def),right.location.resflags,left.location.reference);
  625. end;
  626. end;
  627. {$endif cpuflags}
  628. end;
  629. end;
  630. if releaseright then
  631. location_release(exprasmlist,right.location);
  632. location_release(exprasmlist,left.location);
  633. truelabel:=otlabel;
  634. falselabel:=oflabel;
  635. end;
  636. {*****************************************************************************
  637. SecondArrayConstruct
  638. *****************************************************************************}
  639. const
  640. vtInteger = 0;
  641. vtBoolean = 1;
  642. vtChar = 2;
  643. vtExtended = 3;
  644. vtString = 4;
  645. vtPointer = 5;
  646. vtPChar = 6;
  647. vtObject = 7;
  648. vtClass = 8;
  649. vtWideChar = 9;
  650. vtPWideChar = 10;
  651. vtAnsiString = 11;
  652. vtCurrency = 12;
  653. vtVariant = 13;
  654. vtInterface = 14;
  655. vtWideString = 15;
  656. vtInt64 = 16;
  657. vtQWord = 17;
  658. procedure tcgarrayconstructornode.pass_2;
  659. var
  660. hp : tarrayconstructornode;
  661. href : treference;
  662. lt : tdef;
  663. vaddr : boolean;
  664. vtype : longint;
  665. freetemp,
  666. dovariant : boolean;
  667. elesize : longint;
  668. tmpreg : tregister;
  669. begin
  670. dovariant:=(nf_forcevaria in flags) or tarraydef(resulttype.def).isvariant;
  671. if dovariant then
  672. elesize:=8
  673. else
  674. elesize:=tarraydef(resulttype.def).elesize;
  675. if nf_cargs in flags then
  676. location_reset(location,LOC_VOID,OS_NO)
  677. else
  678. location_reset(location,LOC_CREFERENCE,OS_NO);
  679. if not(nf_cargs in flags) then
  680. begin
  681. { Allocate always a temp, also if no elements are required, to
  682. be sure that location is valid (PFV) }
  683. if tarraydef(resulttype.def).highrange=-1 then
  684. tg.GetTemp(exprasmlist,elesize,tt_normal,location.reference)
  685. else
  686. tg.GetTemp(exprasmlist,(tarraydef(resulttype.def).highrange+1)*elesize,tt_normal,location.reference);
  687. href:=location.reference;
  688. end;
  689. hp:=self;
  690. while assigned(hp) do
  691. begin
  692. if assigned(hp.left) then
  693. begin
  694. freetemp:=true;
  695. secondpass(hp.left);
  696. if codegenerror then
  697. exit;
  698. if dovariant then
  699. begin
  700. { find the correct vtype value }
  701. vtype:=$ff;
  702. vaddr:=false;
  703. lt:=hp.left.resulttype.def;
  704. case lt.deftype of
  705. enumdef,
  706. orddef :
  707. begin
  708. if is_64bit(lt) then
  709. begin
  710. case torddef(lt).typ of
  711. s64bit:
  712. vtype:=vtInt64;
  713. u64bit:
  714. vtype:=vtQWord;
  715. end;
  716. if not(nf_cargs in flags) then
  717. begin
  718. freetemp:=false;
  719. vaddr:=true;
  720. end;
  721. end
  722. else if (lt.deftype=enumdef) or
  723. is_integer(lt) then
  724. vtype:=vtInteger
  725. else
  726. if is_boolean(lt) then
  727. vtype:=vtBoolean
  728. else
  729. if (lt.deftype=orddef) then
  730. begin
  731. case torddef(lt).typ of
  732. uchar:
  733. vtype:=vtChar;
  734. uwidechar:
  735. vtype:=vtWideChar;
  736. end;
  737. end;
  738. end;
  739. floatdef :
  740. begin
  741. vtype:=vtExtended;
  742. if not(nf_cargs in flags) then
  743. begin
  744. freetemp:=false;
  745. vaddr:=true;
  746. end;
  747. end;
  748. procvardef,
  749. pointerdef :
  750. begin
  751. if is_pchar(lt) then
  752. vtype:=vtPChar
  753. else
  754. vtype:=vtPointer;
  755. end;
  756. variantdef :
  757. begin
  758. vtype:=vtVariant;
  759. vaddr:=true;
  760. freetemp:=false;
  761. end;
  762. classrefdef :
  763. vtype:=vtClass;
  764. objectdef :
  765. vtype:=vtObject;
  766. stringdef :
  767. begin
  768. if is_shortstring(lt) then
  769. begin
  770. vtype:=vtString;
  771. vaddr:=true;
  772. freetemp:=false;
  773. end
  774. else
  775. if is_ansistring(lt) then
  776. begin
  777. vtype:=vtAnsiString;
  778. freetemp:=false;
  779. end
  780. else
  781. if is_widestring(lt) then
  782. begin
  783. vtype:=vtWideString;
  784. freetemp:=false;
  785. end;
  786. end;
  787. end;
  788. if vtype=$ff then
  789. internalerror(14357);
  790. { write C style pushes or an pascal array }
  791. if nf_cargs in flags then
  792. begin
  793. if vaddr then
  794. begin
  795. location_force_mem(exprasmlist,hp.left.location);
  796. cg.a_paramaddr_ref(exprasmlist,hp.left.location.reference,paralocdummy);
  797. location_release(exprasmlist,hp.left.location);
  798. if freetemp then
  799. location_freetemp(exprasmlist,hp.left.location);
  800. inc(pushedparasize,pointer_size);
  801. end
  802. else
  803. if vtype in [vtInt64,vtQword,vtExtended] then
  804. push_value_para(exprasmlist,hp.left,pocall_cdecl,0,4,paralocdummy)
  805. else
  806. begin
  807. cg.a_param_loc(exprasmlist,hp.left.location,paralocdummy);
  808. inc(pushedparasize,pointer_size);
  809. end;
  810. end
  811. else
  812. begin
  813. { write changing field update href to the next element }
  814. inc(href.offset,4);
  815. if vaddr then
  816. begin
  817. location_force_mem(exprasmlist,hp.left.location);
  818. {$ifdef newra}
  819. tmpreg:=rg.getaddressregister(exprasmlist);
  820. {$else}
  821. tmpreg:=cg.get_scratch_reg_address(exprasmlist);
  822. {$endif}
  823. cg.a_loadaddr_ref_reg(exprasmlist,hp.left.location.reference,tmpreg);
  824. cg.a_load_reg_ref(exprasmlist,OS_ADDR,tmpreg,href);
  825. {$ifdef newra}
  826. rg.ungetregisterint(exprasmlist,tmpreg);
  827. {$else}
  828. cg.free_scratch_reg(exprasmlist,tmpreg);
  829. {$endif}
  830. location_release(exprasmlist,hp.left.location);
  831. if freetemp then
  832. location_freetemp(exprasmlist,hp.left.location);
  833. end
  834. else
  835. begin
  836. location_release(exprasmlist,hp.left.location);
  837. cg.a_load_loc_ref(exprasmlist,hp.left.location,href);
  838. end;
  839. { update href to the vtype field and write it }
  840. dec(href.offset,4);
  841. cg.a_load_const_ref(exprasmlist, OS_INT,vtype,href);
  842. { goto next array element }
  843. inc(href.offset,8);
  844. end;
  845. end
  846. else
  847. { normal array constructor of the same type }
  848. begin
  849. if is_ansistring(left.resulttype.def) or
  850. is_widestring(left.resulttype.def) or
  851. (left.resulttype.def.deftype=variantdef) then
  852. freetemp:=false;
  853. location_release(exprasmlist,hp.left.location);
  854. case hp.left.location.loc of
  855. LOC_FPUREGISTER,
  856. LOC_CFPUREGISTER :
  857. begin
  858. location_release(exprasmlist,hp.left.location);
  859. cg.a_loadfpu_reg_ref(exprasmlist,hp.left.location.size,hp.left.location.register,href);
  860. end;
  861. LOC_REFERENCE,
  862. LOC_CREFERENCE :
  863. begin
  864. cg.g_concatcopy(exprasmlist,hp.left.location.reference,href,elesize,freetemp,false);
  865. end;
  866. else
  867. begin
  868. if hp.left.location.size in [OS_64,OS_S64] then
  869. cg64.a_load64_loc_ref(exprasmlist,hp.left.location,href)
  870. else
  871. cg.a_load_loc_ref(exprasmlist,hp.left.location,href);
  872. end;
  873. end;
  874. inc(href.offset,elesize);
  875. end;
  876. end;
  877. { load next entry }
  878. hp:=tarrayconstructornode(hp.right);
  879. end;
  880. end;
  881. begin
  882. cloadnode:=tcgloadnode;
  883. cassignmentnode:=tcgassignmentnode;
  884. carrayconstructornode:=tcgarrayconstructornode;
  885. end.
  886. {
  887. $Log$
  888. Revision 1.58 2003-05-12 17:22:00 jonas
  889. * fixed (last?) remaining -tvarsym(X).address to
  890. tg.direction*tvarsym(X).address...
  891. Revision 1.57 2003/05/11 21:37:03 peter
  892. * moved implicit exception frame from ncgutil to psub
  893. * constructor/destructor helpers moved from cobj/ncgutil to psub
  894. Revision 1.56 2003/05/11 14:45:12 peter
  895. * tloadnode does not support objectsymtable,withsymtable anymore
  896. * withnode cleanup
  897. * direct with rewritten to use temprefnode
  898. Revision 1.55 2003/04/29 07:29:14 michael
  899. + Patch from peter to fix wrong pushing of ansistring function results in open array
  900. Revision 1.54 2003/04/27 11:21:33 peter
  901. * aktprocdef renamed to current_procdef
  902. * procinfo renamed to current_procinfo
  903. * procinfo will now be stored in current_module so it can be
  904. cleaned up properly
  905. * gen_main_procsym changed to create_main_proc and release_main_proc
  906. to also generate a tprocinfo structure
  907. * fixed unit implicit initfinal
  908. Revision 1.53 2003/04/27 07:29:50 peter
  909. * current_procdef cleanup, current_procdef is now always nil when parsing
  910. a new procdef declaration
  911. * aktprocsym removed
  912. * lexlevel removed, use symtable.symtablelevel instead
  913. * implicit init/final code uses the normal genentry/genexit
  914. * funcret state checking updated for new funcret handling
  915. Revision 1.52 2003/04/25 20:59:33 peter
  916. * removed funcretn,funcretsym, function result is now in varsym
  917. and aliases for result and function name are added using absolutesym
  918. * vs_hidden parameter for funcret passed in parameter
  919. * vs_hidden fixes
  920. * writenode changed to printnode and released from extdebug
  921. * -vp option added to generate a tree.log with the nodetree
  922. * nicer printnode for statements, callnode
  923. Revision 1.51 2003/04/23 20:16:04 peter
  924. + added currency support based on int64
  925. + is_64bit for use in cg units instead of is_64bitint
  926. * removed cgmessage from n386add, replace with internalerrors
  927. Revision 1.50 2003/04/23 10:12:14 peter
  928. * allow multi pass2 changed to global boolean instead of node flag
  929. Revision 1.49 2003/04/22 23:50:22 peter
  930. * firstpass uses expectloc
  931. * checks if there are differences between the expectloc and
  932. location.loc from secondpass in EXTDEBUG
  933. Revision 1.48 2003/04/22 10:09:35 daniel
  934. + Implemented the actual register allocator
  935. + Scratch registers unavailable when new register allocator used
  936. + maybe_save/maybe_restore unavailable when new register allocator used
  937. Revision 1.47 2003/04/06 21:11:23 olle
  938. * changed newasmsymbol to newasmsymboldata for data symbols
  939. Revision 1.46 2003/03/28 19:16:56 peter
  940. * generic constructor working for i386
  941. * remove fixed self register
  942. * esi added as address register for i386
  943. Revision 1.45 2003/02/19 22:00:14 daniel
  944. * Code generator converted to new register notation
  945. - Horribily outdated todo.txt removed
  946. Revision 1.44 2003/01/08 18:43:56 daniel
  947. * Tregister changed into a record
  948. Revision 1.43 2003/01/05 22:44:14 peter
  949. * remove a lot of code to support typen in loadn-procsym
  950. Revision 1.42 2002/12/20 18:13:46 peter
  951. * fixes for fpu values in arrayconstructor
  952. Revision 1.41 2002/11/27 20:04:39 peter
  953. * cdecl array of const fixes
  954. Revision 1.40 2002/11/25 17:43:18 peter
  955. * splitted defbase in defutil,symutil,defcmp
  956. * merged isconvertable and is_equal into compare_defs(_ext)
  957. * made operator search faster by walking the list only once
  958. Revision 1.39 2002/11/22 16:22:45 jonas
  959. * fixed error in my previous commit (the size of the location of the
  960. funcretnode must be based on the current resulttype of the node and not
  961. the resulttype defined by the function; these can be different in case
  962. of "absolute" declarations)
  963. Revision 1.38 2002/11/18 17:31:54 peter
  964. * pass proccalloption to ret_in_xxx and push_xxx functions
  965. Revision 1.37 2002/11/15 21:16:39 jonas
  966. * proper fix for tw2110, also fixes tb0416 (funcretnode of parent
  967. function was handled wrong inside nested functions/procedures)
  968. Revision 1.36 2002/11/15 01:58:51 peter
  969. * merged changes from 1.0.7 up to 04-11
  970. - -V option for generating bug report tracing
  971. - more tracing for option parsing
  972. - errors for cdecl and high()
  973. - win32 import stabs
  974. - win32 records<=8 are returned in eax:edx (turned off by default)
  975. - heaptrc update
  976. - more info for temp management in .s file with EXTDEBUG
  977. Revision 1.35 2002/10/14 19:44:13 peter
  978. * (hacked) new threadvar relocate code
  979. Revision 1.34 2002/10/13 11:22:06 florian
  980. * fixed threadvars
  981. Revision 1.33 2002/10/03 21:32:02 carl
  982. * bugfix for 2110 (without -Or), wrong checking was done in returntype
  983. Revision 1.32 2002/09/30 07:00:46 florian
  984. * fixes to common code to get the alpha compiler compiled applied
  985. Revision 1.31 2002/09/26 15:02:05 florian
  986. + support of passing variants to "array of const"
  987. Revision 1.30 2002/09/17 18:54:02 jonas
  988. * a_load_reg_reg() now has two size parameters: source and dest. This
  989. allows some optimizations on architectures that don't encode the
  990. register size in the register name.
  991. Revision 1.29 2002/09/07 15:25:03 peter
  992. * old logs removed and tabs fixed
  993. Revision 1.28 2002/09/01 19:26:32 peter
  994. * fixed register variable loading from parasymtable, the call by
  995. reference code was moved wrong
  996. Revision 1.27 2002/09/01 12:15:40 peter
  997. * fixed loading of procvar of object when the object is initialized
  998. with 0
  999. Revision 1.26 2002/08/25 19:25:18 peter
  1000. * sym.insert_in_data removed
  1001. * symtable.insertvardata/insertconstdata added
  1002. * removed insert_in_data call from symtable.insert, it needs to be
  1003. called separatly. This allows to deref the address calculation
  1004. * procedures now calculate the parast addresses after the procedure
  1005. directives are parsed. This fixes the cdecl parast problem
  1006. * push_addr_param has an extra argument that specifies if cdecl is used
  1007. or not
  1008. Revision 1.25 2002/08/23 16:14:48 peter
  1009. * tempgen cleanup
  1010. * tt_noreuse temp type added that will be used in genentrycode
  1011. Revision 1.24 2002/08/17 09:23:35 florian
  1012. * first part of procinfo rewrite
  1013. Revision 1.23 2002/08/14 18:13:28 jonas
  1014. * adapted previous fix to Peter's asmsymbol patch
  1015. Revision 1.22 2002/08/14 18:00:42 jonas
  1016. * fixed tb0403
  1017. Revision 1.21 2002/08/13 21:40:56 florian
  1018. * more fixes for ppc calling conventions
  1019. Revision 1.20 2002/08/11 14:32:26 peter
  1020. * renamed current_library to objectlibrary
  1021. Revision 1.19 2002/08/11 13:24:12 peter
  1022. * saving of asmsymbols in ppu supported
  1023. * asmsymbollist global is removed and moved into a new class
  1024. tasmlibrarydata that will hold the info of a .a file which
  1025. corresponds with a single module. Added librarydata to tmodule
  1026. to keep the library info stored for the module. In the future the
  1027. objectfiles will also be stored to the tasmlibrarydata class
  1028. * all getlabel/newasmsymbol and friends are moved to the new class
  1029. Revision 1.18 2002/08/06 20:55:21 florian
  1030. * first part of ppc calling conventions fix
  1031. Revision 1.17 2002/07/28 09:25:37 carl
  1032. + correct size of parameter (64-bit portability)
  1033. Revision 1.16 2002/07/27 19:53:51 jonas
  1034. + generic implementation of tcg.g_flags2ref()
  1035. * tcg.flags2xxx() now also needs a size parameter
  1036. Revision 1.15 2002/07/20 11:57:54 florian
  1037. * types.pas renamed to defbase.pas because D6 contains a types
  1038. unit so this would conflicts if D6 programms are compiled
  1039. + Willamette/SSE2 instructions to assembler added
  1040. Revision 1.14 2002/07/16 09:17:44 florian
  1041. * threadvar relocation result wasn't handled properly, it could cause
  1042. a crash
  1043. Revision 1.13 2002/07/11 14:41:28 florian
  1044. * start of the new generic parameter handling
  1045. Revision 1.12 2002/07/07 09:52:32 florian
  1046. * powerpc target fixed, very simple units can be compiled
  1047. * some basic stuff for better callparanode handling, far from being finished
  1048. Revision 1.11 2002/07/01 18:46:23 peter
  1049. * internal linker
  1050. * reorganized aasm layer
  1051. Revision 1.10 2002/07/01 16:23:53 peter
  1052. * cg64 patch
  1053. * basics for currency
  1054. * asnode updates for class and interface (not finished)
  1055. Revision 1.9 2002/05/20 13:30:40 carl
  1056. * bugfix of hdisponen (base must be set, not index)
  1057. * more portability fixes
  1058. }