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