ncgld.pas 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107
  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. tcgfuncretnode = class(tfuncretnode)
  32. procedure pass_2;override;
  33. end;
  34. tcgarrayconstructornode = class(tarrayconstructornode)
  35. procedure pass_2;override;
  36. end;
  37. implementation
  38. uses
  39. systems,
  40. verbose,globtype,globals,
  41. symconst,symtype,symdef,symsym,symtable,defutil,paramgr,
  42. ncnv,ncon,nmem,
  43. aasmbase,aasmtai,aasmcpu,regvars,
  44. cginfo,cgbase,pass_2,
  45. cpubase,cpuinfo,cpupara,
  46. tgobj,ncgutil,cgobj,rgobj,rgcpu;
  47. {*****************************************************************************
  48. SecondLoad
  49. *****************************************************************************}
  50. procedure tcgloadnode.pass_2;
  51. var
  52. intreg,
  53. hregister : tregister;
  54. symtabletype : tsymtabletype;
  55. i : longint;
  56. href : treference;
  57. newsize : tcgsize;
  58. pushed : tpushedsaved;
  59. dorelocatelab,
  60. norelocatelab : tasmlabel;
  61. begin
  62. { we don't know the size of all arrays }
  63. newsize:=def_cgsize(resulttype.def);
  64. location_reset(location,LOC_REFERENCE,newsize);
  65. case symtableentry.typ of
  66. absolutesym :
  67. begin
  68. { this is only for toasm and toaddr }
  69. if (tabsolutesym(symtableentry).abstyp=toaddr) then
  70. begin
  71. {$ifdef i386}
  72. if tabsolutesym(symtableentry).absseg then
  73. location.reference.segment:=R_FS;
  74. {$endif i386}
  75. location.reference.offset:=tabsolutesym(symtableentry).address;
  76. end
  77. else
  78. location.reference.symbol:=objectlibrary.newasmsymbol(tabsolutesym(symtableentry).mangledname);
  79. end;
  80. constsym:
  81. begin
  82. if tconstsym(symtableentry).consttyp=constresourcestring then
  83. begin
  84. location_reset(location,LOC_CREFERENCE,OS_ADDR);
  85. location.reference.symbol:=objectlibrary.newasmsymbol(tconstsym(symtableentry).owner.name^+'_RESOURCESTRINGLIST');
  86. location.reference.offset:=tconstsym(symtableentry).resstrindex*16+8;
  87. end
  88. else
  89. internalerror(22798);
  90. end;
  91. varsym :
  92. begin
  93. symtabletype:=symtable.symtabletype;
  94. hregister:=R_NO;
  95. { C variable }
  96. if (vo_is_C_var in tvarsym(symtableentry).varoptions) then
  97. begin
  98. location.reference.symbol:=objectlibrary.newasmsymbol(tvarsym(symtableentry).mangledname);
  99. end
  100. { DLL variable }
  101. else if (vo_is_dll_var in tvarsym(symtableentry).varoptions) then
  102. begin
  103. hregister:=rg.getaddressregister(exprasmlist);
  104. location.reference.symbol:=objectlibrary.newasmsymbol(tvarsym(symtableentry).mangledname);
  105. cg.a_load_ref_reg(exprasmlist,OS_ADDR,location.reference,hregister);
  106. reference_reset_base(location.reference,hregister,0);
  107. end
  108. { external variable }
  109. else if (vo_is_external in tvarsym(symtableentry).varoptions) then
  110. begin
  111. location.reference.symbol:=objectlibrary.newasmsymbol(tvarsym(symtableentry).mangledname);
  112. end
  113. { thread variable }
  114. else if (vo_is_thread_var in tvarsym(symtableentry).varoptions) then
  115. begin
  116. objectlibrary.getlabel(dorelocatelab);
  117. objectlibrary.getlabel(norelocatelab);
  118. { we've to allocate the register before we save the used registers }
  119. hregister:=rg.getaddressregister(exprasmlist);
  120. reference_reset_symbol(href,objectlibrary.newasmsymbol('FPC_THREADVAR_RELOCATE'),0);
  121. cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,hregister);
  122. cg.a_cmp_const_reg_label(exprasmlist,OS_ADDR,OC_NE,0,hregister,dorelocatelab);
  123. { no relocation needed, load the address of the variable only, the
  124. layout of a threadvar is (4 bytes pointer):
  125. 0 - Threadvar index
  126. 4 - Threadvar value in single threading }
  127. reference_reset_symbol(href,objectlibrary.newasmsymbol(tvarsym(symtableentry).mangledname),POINTER_SIZE);
  128. cg.a_loadaddr_ref_reg(exprasmlist,href,hregister);
  129. cg.a_jmp_always(exprasmlist,norelocatelab);
  130. cg.a_label(exprasmlist,dorelocatelab);
  131. { don't save the allocated register else the result will be destroyed later }
  132. rg.saveusedregisters(exprasmlist,pushed,[accumulator]-[hregister]);
  133. reference_reset_symbol(href,objectlibrary.newasmsymbol(tvarsym(symtableentry).mangledname),0);
  134. cg.a_param_ref(exprasmlist,OS_ADDR,href,paramanager.getintparaloc(1));
  135. { the called procedure isn't allowed to change }
  136. { any register except EAX }
  137. cg.a_call_reg(exprasmlist,hregister);
  138. cg.a_load_reg_reg(exprasmlist,OS_INT,OS_ADDR,accumulator,hregister);
  139. rg.restoreusedregisters(exprasmlist,pushed);
  140. cg.a_label(exprasmlist,norelocatelab);
  141. location.reference.base:=hregister;
  142. end
  143. { normal variable }
  144. else
  145. begin
  146. { in case it is a register variable: }
  147. if tvarsym(symtableentry).reg<>R_NO then
  148. begin
  149. if tvarsym(symtableentry).reg in fpuregs then
  150. begin
  151. location_reset(location,LOC_CFPUREGISTER,def_cgsize(resulttype.def));
  152. location.register:=tvarsym(symtableentry).reg;
  153. end
  154. else
  155. begin
  156. intreg:=rg.makeregsize(tvarsym(symtableentry).reg,OS_INT);
  157. if (intreg in general_registers) and
  158. (not rg.regvar_loaded[intreg]) then
  159. load_regvar(exprasmlist,tvarsym(symtableentry));
  160. location_reset(location,LOC_CREGISTER,cg.reg_cgsize(tvarsym(symtableentry).reg));
  161. location.register:=tvarsym(symtableentry).reg;
  162. exclude(rg.unusedregsint,intreg);
  163. end;
  164. end
  165. else
  166. begin
  167. case symtabletype of
  168. localsymtable,
  169. parasymtable,
  170. inlinelocalsymtable,
  171. inlineparasymtable :
  172. begin
  173. location.reference.base:=procinfo.framepointer;
  174. if (symtabletype in [inlinelocalsymtable,
  175. localsymtable])
  176. {$ifdef powerpc}
  177. { the ifdef is only for speed reasons }
  178. and not(target_info.system in [system_powerpc_linux,system_powerpc_macos])
  179. {$endif powerpc}
  180. then
  181. location.reference.offset:=
  182. tvarsym(symtableentry).address-symtable.address_fixup
  183. else
  184. location.reference.offset:=
  185. tvarsym(symtableentry).address+symtable.address_fixup;
  186. {$ifndef powerpc}
  187. if (symtabletype in [localsymtable,inlinelocalsymtable]) then
  188. begin
  189. if use_esp_stackframe then
  190. dec(location.reference.offset,
  191. tvarsym(symtableentry).getvaluesize)
  192. else
  193. location.reference.offset:=-location.reference.offset;
  194. end;
  195. {$endif powerpc}
  196. if (lexlevel>symtable.symtablelevel) then
  197. begin
  198. hregister:=rg.getaddressregister(exprasmlist);
  199. { make a reference }
  200. reference_reset_base(href,procinfo.framepointer,procinfo.framepointer_offset);
  201. cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,hregister);
  202. { walk parents }
  203. i:=lexlevel-1;
  204. while (i>symtable.symtablelevel) do
  205. begin
  206. { make a reference }
  207. reference_reset_base(href,hregister,target_info.first_parm_offset);
  208. cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,hregister);
  209. dec(i);
  210. end;
  211. location.reference.base:=hregister;
  212. end;
  213. end;
  214. globalsymtable,
  215. staticsymtable :
  216. begin
  217. location.reference.symbol:=objectlibrary.newasmsymbol(tvarsym(symtableentry).mangledname);
  218. end;
  219. stt_exceptsymtable:
  220. begin
  221. location.reference.base:=procinfo.framepointer;
  222. location.reference.offset:=tvarsym(symtableentry).address;
  223. end;
  224. objectsymtable:
  225. begin
  226. if (sp_static in tvarsym(symtableentry).symoptions) then
  227. location.reference.symbol:=objectlibrary.newasmsymbol(tvarsym(symtableentry).mangledname)
  228. else
  229. begin
  230. rg.getexplicitregisterint(exprasmlist,SELF_POINTER_REG);
  231. location.reference.base:=SELF_POINTER_REG;
  232. location.reference.offset:=tvarsym(symtableentry).address;
  233. end;
  234. end;
  235. withsymtable:
  236. begin
  237. if nf_islocal in tnode(twithsymtable(symtable).withnode).flags then
  238. location.reference:=twithnode(twithsymtable(symtable).withnode).withreference
  239. else
  240. begin
  241. location.reference.base:=rg.getaddressregister(exprasmlist);
  242. cg.a_load_ref_reg(exprasmlist,OS_ADDR,
  243. twithnode(twithsymtable(symtable).withnode).withreference,
  244. location.reference.base);
  245. end;
  246. inc(location.reference.offset,tvarsym(symtableentry).address);
  247. end;
  248. end;
  249. end;
  250. end;
  251. { handle call by reference variables }
  252. if (symtabletype in [parasymtable,inlineparasymtable]) then
  253. begin
  254. { in case call by reference, then calculate. Open array
  255. is always an reference! }
  256. if (tvarsym(symtableentry).varspez in [vs_var,vs_out]) or
  257. paramanager.push_addr_param(tvarsym(symtableentry).vartype.def,tprocdef(symtable.defowner).proccalloption) then
  258. begin
  259. if hregister=R_NO then
  260. hregister:=rg.getaddressregister(exprasmlist);
  261. { we need to load only an address }
  262. location.size:=OS_ADDR;
  263. cg.a_load_loc_reg(exprasmlist,location,hregister);
  264. location_reset(location,LOC_REFERENCE,newsize);
  265. location.reference.base:=hregister;
  266. end;
  267. end;
  268. end;
  269. procsym:
  270. begin
  271. if assigned(left) then
  272. begin
  273. {
  274. THIS IS A TERRIBLE HACK!!!!!! WHICH WILL NOT WORK
  275. ON 64-BIT SYSTEMS: SINCE PROCSYM FOR METHODS
  276. CONSISTS OF TWO OS_ADDR, so you cannot set it
  277. to OS_64 - how to solve?? Carl
  278. }
  279. if (sizeof(aword) = 4) then
  280. location_reset(location,LOC_CREFERENCE,OS_64)
  281. else
  282. internalerror(20020520);
  283. tg.GetTemp(exprasmlist,2*POINTER_SIZE,tt_normal,location.reference);
  284. secondpass(left);
  285. { load class instance address }
  286. case left.location.loc of
  287. LOC_CREGISTER,
  288. LOC_REGISTER:
  289. begin
  290. hregister:=left.location.register;
  291. if is_object(left.resulttype.def) then
  292. CGMessage(cg_e_illegal_expression);
  293. end;
  294. LOC_CREFERENCE,
  295. LOC_REFERENCE:
  296. begin
  297. hregister:=rg.getaddressregister(exprasmlist);
  298. if is_class_or_interface(left.resulttype.def) then
  299. cg.a_load_ref_reg(exprasmlist,OS_ADDR,left.location.reference,hregister)
  300. else
  301. cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,hregister);
  302. location_release(exprasmlist,left.location);
  303. location_freetemp(exprasmlist,left.location);
  304. end;
  305. else
  306. internalerror(26019);
  307. end;
  308. { store the class instance address }
  309. href:=location.reference;
  310. inc(href.offset,POINTER_SIZE);
  311. cg.a_load_reg_ref(exprasmlist,OS_ADDR,hregister,href);
  312. { virtual method ? }
  313. if (po_virtualmethod in tprocdef(resulttype.def).procoptions) then
  314. begin
  315. { load vmt pointer }
  316. reference_reset_base(href,hregister,0);
  317. reference_release(exprasmlist,href);
  318. hregister:=rg.getaddressregister(exprasmlist);
  319. cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,hregister);
  320. reference_reset_base(href,hregister,tprocdef(resulttype.def)._class.vmtmethodoffset(
  321. tprocdef(resulttype.def).extnumber));
  322. reference_release(exprasmlist,href);
  323. { load method address }
  324. hregister:=rg.getaddressregister(exprasmlist);
  325. cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,hregister);
  326. { ... and store it }
  327. cg.a_load_reg_ref(exprasmlist,OS_ADDR,hregister,location.reference);
  328. rg.ungetaddressregister(exprasmlist,hregister);
  329. end
  330. else
  331. begin
  332. { we don't use the hregister }
  333. rg.ungetregister(exprasmlist,hregister);
  334. { load address of the function }
  335. reference_reset_symbol(href,objectlibrary.newasmsymbol(tprocdef(resulttype.def).mangledname),0);
  336. hregister:=cg.get_scratch_reg_address(exprasmlist);
  337. cg.a_loadaddr_ref_reg(exprasmlist,href,hregister);
  338. cg.a_load_reg_ref(exprasmlist,OS_ADDR,hregister,location.reference);
  339. cg.free_scratch_reg(exprasmlist,hregister);
  340. end;
  341. end
  342. else
  343. begin
  344. {!!!!! Be aware, work on virtual methods too }
  345. location.reference.symbol:=objectlibrary.newasmsymbol(tprocdef(resulttype.def).mangledname);
  346. end;
  347. end;
  348. typedconstsym :
  349. begin
  350. location.reference.symbol:=objectlibrary.newasmsymbol(ttypedconstsym(symtableentry).mangledname);
  351. end;
  352. else internalerror(4);
  353. end;
  354. end;
  355. {*****************************************************************************
  356. SecondAssignment
  357. *****************************************************************************}
  358. procedure tcgassignmentnode.pass_2;
  359. var
  360. otlabel,hlabel,oflabel : tasmlabel;
  361. fputyp : tfloattype;
  362. href : treference;
  363. releaseright : boolean;
  364. pushedregs : tmaybesave;
  365. cgsize : tcgsize;
  366. begin
  367. otlabel:=truelabel;
  368. oflabel:=falselabel;
  369. objectlibrary.getlabel(truelabel);
  370. objectlibrary.getlabel(falselabel);
  371. {
  372. in most cases we can process first the right node which contains
  373. the most complex code. But not when the result is in the flags, then
  374. loading the left node afterwards can destroy the flags.
  375. when the right node returns as LOC_JUMP then we will generate
  376. the following code:
  377. rightnode
  378. true:
  379. leftnode
  380. assign 1
  381. false:
  382. leftnode
  383. assign 0
  384. }
  385. { Try to determine which side to calculate first, }
  386. if (right.location.loc<>LOC_FLAGS) and
  387. ((right.location.loc=LOC_JUMP) or
  388. (right.registers32>=left.registers32)) then
  389. begin
  390. secondpass(right);
  391. { increment source reference counter, this is
  392. useless for string constants}
  393. if (right.resulttype.def.needs_inittable) and
  394. (right.nodetype<>stringconstn) then
  395. cg.g_incrrefcount(exprasmlist,right.resulttype.def,right.location.reference);
  396. if codegenerror then
  397. exit;
  398. { We skip the generation of the left node when it's a jump, see
  399. explanation above }
  400. if (right.location.loc<>LOC_JUMP) and
  401. not(nf_concat_string in flags) then
  402. begin
  403. { left can't be never a 64 bit LOC_REGISTER, so the 3. arg }
  404. { can be false }
  405. maybe_save(exprasmlist,left.registers32,right.location,pushedregs);
  406. secondpass(left);
  407. { decrement destination reference counter }
  408. if (left.resulttype.def.needs_inittable) then
  409. cg.g_decrrefcount(exprasmlist,left.resulttype.def,left.location.reference);
  410. maybe_restore(exprasmlist,right.location,pushedregs);
  411. if codegenerror then
  412. exit;
  413. end;
  414. end
  415. else
  416. begin
  417. { calculate left sides }
  418. { don't do it yet if it's a crgister (JM) }
  419. if not(nf_concat_string in flags) then
  420. begin
  421. secondpass(left);
  422. { decrement destination reference counter }
  423. if (left.resulttype.def.needs_inittable) then
  424. cg.g_decrrefcount(exprasmlist,left.resulttype.def,left.location.reference);
  425. if codegenerror then
  426. exit;
  427. end;
  428. { left can't be never a 64 bit LOC_REGISTER, so the 3. arg }
  429. { can be false }
  430. maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
  431. secondpass(right);
  432. { increment source reference counter, this is
  433. useless for string constants}
  434. if (right.resulttype.def.needs_inittable) and
  435. (right.nodetype<>stringconstn) then
  436. cg.g_incrrefcount(exprasmlist,right.resulttype.def,right.location.reference);
  437. maybe_restore(exprasmlist,left.location,pushedregs);
  438. if codegenerror then
  439. exit;
  440. end;
  441. if not(left.location.loc in [LOC_REFERENCE,LOC_CFPUREGISTER,
  442. {$ifdef SUPPORT_MMX}LOC_CMMXREGISTER,{$endif}
  443. LOC_CREGISTER]) then
  444. begin
  445. CGMessage(cg_e_illegal_expression);
  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. cg.a_load_reg_ref(exprasmlist,OS_8,rg.makeregsize(right.location.register,OS_8),href);
  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. maybe_save(exprasmlist,left.registers32,right.location,pushedregs);
  586. secondpass(left);
  587. maybe_restore(exprasmlist,right.location,pushedregs);
  588. if codegenerror then
  589. exit;
  590. cg.a_load_const_loc(exprasmlist,1,left.location);
  591. location_release(exprasmlist,left.location);
  592. cg.a_jmp_always(exprasmlist,hlabel);
  593. { generate the leftnode for the false case }
  594. cg.a_label(exprasmlist,falselabel);
  595. maybe_save(exprasmlist,left.registers32,right.location,pushedregs);
  596. secondpass(left);
  597. maybe_restore(exprasmlist,right.location,pushedregs);
  598. if codegenerror then
  599. exit;
  600. cg.a_load_const_loc(exprasmlist,0,left.location);
  601. cg.a_label(exprasmlist,hlabel);
  602. end;
  603. {$ifdef cpuflags}
  604. LOC_FLAGS :
  605. begin
  606. // this can be a wordbool or longbool too, no?
  607. if left.location.loc=LOC_CREGISTER then
  608. cg.g_flags2reg(exprasmlist,def_cgsize(left.resulttype.def),right.location.resflags,left.location.register)
  609. else
  610. begin
  611. if not(left.location.loc = LOC_REFERENCE) then
  612. internalerror(200203273);
  613. cg.g_flags2ref(exprasmlist,def_cgsize(left.resulttype.def),right.location.resflags,left.location.reference);
  614. end;
  615. end;
  616. {$endif cpuflags}
  617. end;
  618. end;
  619. if releaseright then
  620. location_release(exprasmlist,right.location);
  621. location_release(exprasmlist,left.location);
  622. truelabel:=otlabel;
  623. falselabel:=oflabel;
  624. end;
  625. {*****************************************************************************
  626. SecondFuncRet
  627. *****************************************************************************}
  628. procedure tcgfuncretnode.pass_2;
  629. var
  630. hreg : tregister;
  631. href : treference;
  632. pp : tprocinfo;
  633. hr_valid : boolean;
  634. i : integer;
  635. begin
  636. location_reset(location,LOC_REFERENCE,def_cgsize(resulttype.def));
  637. hr_valid:=false;
  638. if (not inlining_procedure) and
  639. (lexlevel<>funcretsym.owner.symtablelevel) then
  640. begin
  641. hreg:=rg.getaddressregister(exprasmlist);
  642. hr_valid:=true;
  643. reference_reset_base(href,procinfo.framepointer,procinfo.framepointer_offset);
  644. cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,hreg);
  645. { walk up the stack frame }
  646. pp:=procinfo.parent;
  647. i:=lexlevel-1;
  648. while i>funcretsym.owner.symtablelevel do
  649. begin
  650. reference_reset_base(href,hreg,pp.framepointer_offset);
  651. cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,hreg);
  652. pp:=pp.parent;
  653. dec(i);
  654. end;
  655. location.reference.base:=hreg;
  656. location.reference.offset:=pp.return_offset;
  657. end
  658. else
  659. begin
  660. location.reference.base:=procinfo.framepointer;
  661. location.reference.offset:=procinfo.return_offset;
  662. end;
  663. if paramanager.ret_in_param(funcretsym.returntype.def,
  664. tprocdef(funcretsym.owner.defowner).proccalloption) then
  665. begin
  666. { the parameter is actual a pointer to the value }
  667. if not hr_valid then
  668. hreg:=rg.getaddressregister(exprasmlist);
  669. cg.a_load_ref_reg(exprasmlist,OS_ADDR,location.reference,hreg);
  670. location.reference.base:=hreg;
  671. location.reference.offset:=0;
  672. end;
  673. end;
  674. {*****************************************************************************
  675. SecondArrayConstruct
  676. *****************************************************************************}
  677. const
  678. vtInteger = 0;
  679. vtBoolean = 1;
  680. vtChar = 2;
  681. vtExtended = 3;
  682. vtString = 4;
  683. vtPointer = 5;
  684. vtPChar = 6;
  685. vtObject = 7;
  686. vtClass = 8;
  687. vtWideChar = 9;
  688. vtPWideChar = 10;
  689. vtAnsiString = 11;
  690. vtCurrency = 12;
  691. vtVariant = 13;
  692. vtInterface = 14;
  693. vtWideString = 15;
  694. vtInt64 = 16;
  695. vtQWord = 17;
  696. procedure tcgarrayconstructornode.pass_2;
  697. var
  698. hp : tarrayconstructornode;
  699. href : treference;
  700. lt : tdef;
  701. vaddr : boolean;
  702. vtype : longint;
  703. freetemp,
  704. dovariant : boolean;
  705. elesize : longint;
  706. tmpreg : tregister;
  707. begin
  708. dovariant:=(nf_forcevaria in flags) or tarraydef(resulttype.def).isvariant;
  709. if dovariant then
  710. elesize:=8
  711. else
  712. elesize:=tarraydef(resulttype.def).elesize;
  713. location_reset(location,LOC_REFERENCE,OS_NO);
  714. if not(nf_cargs in flags) then
  715. begin
  716. { Allocate always a temp, also if no elements are required, to
  717. be sure that location is valid (PFV) }
  718. if tarraydef(resulttype.def).highrange=-1 then
  719. tg.GetTemp(exprasmlist,elesize,tt_normal,location.reference)
  720. else
  721. tg.GetTemp(exprasmlist,(tarraydef(resulttype.def).highrange+1)*elesize,tt_normal,location.reference);
  722. href:=location.reference;
  723. end;
  724. hp:=self;
  725. while assigned(hp) do
  726. begin
  727. if assigned(hp.left) then
  728. begin
  729. freetemp:=true;
  730. secondpass(hp.left);
  731. if codegenerror then
  732. exit;
  733. if dovariant then
  734. begin
  735. { find the correct vtype value }
  736. vtype:=$ff;
  737. vaddr:=false;
  738. lt:=hp.left.resulttype.def;
  739. case lt.deftype of
  740. enumdef,
  741. orddef :
  742. begin
  743. if is_64bitint(lt) then
  744. begin
  745. case torddef(lt).typ of
  746. s64bit:
  747. vtype:=vtInt64;
  748. u64bit:
  749. vtype:=vtQWord;
  750. end;
  751. if not(nf_cargs in flags) then
  752. begin
  753. freetemp:=false;
  754. vaddr:=true;
  755. end;
  756. end
  757. else if (lt.deftype=enumdef) or
  758. is_integer(lt) then
  759. vtype:=vtInteger
  760. else
  761. if is_boolean(lt) then
  762. vtype:=vtBoolean
  763. else
  764. if (lt.deftype=orddef) then
  765. begin
  766. case torddef(lt).typ of
  767. uchar:
  768. vtype:=vtChar;
  769. uwidechar:
  770. vtype:=vtWideChar;
  771. end;
  772. end;
  773. end;
  774. floatdef :
  775. begin
  776. vtype:=vtExtended;
  777. if not(nf_cargs in flags) then
  778. begin
  779. freetemp:=false;
  780. vaddr:=true;
  781. end;
  782. end;
  783. procvardef,
  784. pointerdef :
  785. begin
  786. if is_pchar(lt) then
  787. vtype:=vtPChar
  788. else
  789. vtype:=vtPointer;
  790. end;
  791. variantdef :
  792. begin
  793. vtype:=vtVariant;
  794. vaddr:=true;
  795. freetemp:=false;
  796. end;
  797. classrefdef :
  798. vtype:=vtClass;
  799. objectdef :
  800. vtype:=vtObject;
  801. stringdef :
  802. begin
  803. if is_shortstring(lt) then
  804. begin
  805. vtype:=vtString;
  806. vaddr:=true;
  807. freetemp:=false;
  808. end
  809. else
  810. if is_ansistring(lt) then
  811. begin
  812. vtype:=vtAnsiString;
  813. freetemp:=false;
  814. end
  815. else
  816. if is_widestring(lt) then
  817. begin
  818. vtype:=vtWideString;
  819. freetemp:=false;
  820. end;
  821. end;
  822. end;
  823. if vtype=$ff then
  824. internalerror(14357);
  825. { write C style pushes or an pascal array }
  826. if nf_cargs in flags then
  827. begin
  828. if vaddr then
  829. begin
  830. location_force_mem(exprasmlist,hp.left.location);
  831. cg.a_paramaddr_ref(exprasmlist,hp.left.location.reference,paralocdummy);
  832. location_release(exprasmlist,hp.left.location);
  833. if freetemp then
  834. location_freetemp(exprasmlist,hp.left.location);
  835. inc(pushedparasize,pointer_size);
  836. end
  837. else
  838. if vtype in [vtInt64,vtQword,vtExtended] then
  839. push_value_para(hp.left,pocall_cdecl,0,4,paralocdummy)
  840. else
  841. begin
  842. cg.a_param_loc(exprasmlist,hp.left.location,paralocdummy);
  843. inc(pushedparasize,pointer_size);
  844. end;
  845. end
  846. else
  847. begin
  848. { write changing field update href to the next element }
  849. inc(href.offset,4);
  850. if vaddr then
  851. begin
  852. location_force_mem(exprasmlist,hp.left.location);
  853. tmpreg:=cg.get_scratch_reg_address(exprasmlist);
  854. cg.a_loadaddr_ref_reg(exprasmlist,hp.left.location.reference,tmpreg);
  855. cg.a_load_reg_ref(exprasmlist,cg.reg_cgsize(tmpreg),tmpreg,href);
  856. cg.free_scratch_reg(exprasmlist,tmpreg);
  857. location_release(exprasmlist,hp.left.location);
  858. if freetemp then
  859. location_freetemp(exprasmlist,hp.left.location);
  860. end
  861. else
  862. begin
  863. location_release(exprasmlist,hp.left.location);
  864. cg.a_load_loc_ref(exprasmlist,hp.left.location,href);
  865. end;
  866. { update href to the vtype field and write it }
  867. dec(href.offset,4);
  868. cg.a_load_const_ref(exprasmlist, OS_INT,vtype,href);
  869. { goto next array element }
  870. inc(href.offset,8);
  871. end;
  872. end
  873. else
  874. { normal array constructor of the same type }
  875. begin
  876. location_release(exprasmlist,hp.left.location);
  877. case hp.left.location.loc of
  878. LOC_FPUREGISTER,
  879. LOC_CFPUREGISTER :
  880. begin
  881. location_release(exprasmlist,hp.left.location);
  882. cg.a_loadfpu_reg_ref(exprasmlist,hp.left.location.size,hp.left.location.register,href);
  883. end;
  884. LOC_REFERENCE,
  885. LOC_CREFERENCE :
  886. begin
  887. cg.g_concatcopy(exprasmlist,hp.left.location.reference,href,elesize,freetemp,false);
  888. end;
  889. else
  890. begin
  891. if hp.left.location.size in [OS_64,OS_S64] then
  892. cg64.a_load64_loc_ref(exprasmlist,hp.left.location,href)
  893. else
  894. cg.a_load_loc_ref(exprasmlist,hp.left.location,href);
  895. end;
  896. end;
  897. inc(href.offset,elesize);
  898. end;
  899. end;
  900. { load next entry }
  901. hp:=tarrayconstructornode(hp.right);
  902. end;
  903. end;
  904. begin
  905. cloadnode:=tcgloadnode;
  906. cassignmentnode:=tcgassignmentnode;
  907. cfuncretnode:=tcgfuncretnode;
  908. carrayconstructornode:=tcgarrayconstructornode;
  909. end.
  910. {
  911. $Log$
  912. Revision 1.43 2003-01-05 22:44:14 peter
  913. * remove a lot of code to support typen in loadn-procsym
  914. Revision 1.42 2002/12/20 18:13:46 peter
  915. * fixes for fpu values in arrayconstructor
  916. Revision 1.41 2002/11/27 20:04:39 peter
  917. * cdecl array of const fixes
  918. Revision 1.40 2002/11/25 17:43:18 peter
  919. * splitted defbase in defutil,symutil,defcmp
  920. * merged isconvertable and is_equal into compare_defs(_ext)
  921. * made operator search faster by walking the list only once
  922. Revision 1.39 2002/11/22 16:22:45 jonas
  923. * fixed error in my previous commit (the size of the location of the
  924. funcretnode must be based on the current resulttype of the node and not
  925. the resulttype defined by the function; these can be different in case
  926. of "absolute" declarations)
  927. Revision 1.38 2002/11/18 17:31:54 peter
  928. * pass proccalloption to ret_in_xxx and push_xxx functions
  929. Revision 1.37 2002/11/15 21:16:39 jonas
  930. * proper fix for tw2110, also fixes tb0416 (funcretnode of parent
  931. function was handled wrong inside nested functions/procedures)
  932. Revision 1.36 2002/11/15 01:58:51 peter
  933. * merged changes from 1.0.7 up to 04-11
  934. - -V option for generating bug report tracing
  935. - more tracing for option parsing
  936. - errors for cdecl and high()
  937. - win32 import stabs
  938. - win32 records<=8 are returned in eax:edx (turned off by default)
  939. - heaptrc update
  940. - more info for temp management in .s file with EXTDEBUG
  941. Revision 1.35 2002/10/14 19:44:13 peter
  942. * (hacked) new threadvar relocate code
  943. Revision 1.34 2002/10/13 11:22:06 florian
  944. * fixed threadvars
  945. Revision 1.33 2002/10/03 21:32:02 carl
  946. * bugfix for 2110 (without -Or), wrong checking was done in returntype
  947. Revision 1.32 2002/09/30 07:00:46 florian
  948. * fixes to common code to get the alpha compiler compiled applied
  949. Revision 1.31 2002/09/26 15:02:05 florian
  950. + support of passing variants to "array of const"
  951. Revision 1.30 2002/09/17 18:54:02 jonas
  952. * a_load_reg_reg() now has two size parameters: source and dest. This
  953. allows some optimizations on architectures that don't encode the
  954. register size in the register name.
  955. Revision 1.29 2002/09/07 15:25:03 peter
  956. * old logs removed and tabs fixed
  957. Revision 1.28 2002/09/01 19:26:32 peter
  958. * fixed register variable loading from parasymtable, the call by
  959. reference code was moved wrong
  960. Revision 1.27 2002/09/01 12:15:40 peter
  961. * fixed loading of procvar of object when the object is initialized
  962. with 0
  963. Revision 1.26 2002/08/25 19:25:18 peter
  964. * sym.insert_in_data removed
  965. * symtable.insertvardata/insertconstdata added
  966. * removed insert_in_data call from symtable.insert, it needs to be
  967. called separatly. This allows to deref the address calculation
  968. * procedures now calculate the parast addresses after the procedure
  969. directives are parsed. This fixes the cdecl parast problem
  970. * push_addr_param has an extra argument that specifies if cdecl is used
  971. or not
  972. Revision 1.25 2002/08/23 16:14:48 peter
  973. * tempgen cleanup
  974. * tt_noreuse temp type added that will be used in genentrycode
  975. Revision 1.24 2002/08/17 09:23:35 florian
  976. * first part of procinfo rewrite
  977. Revision 1.23 2002/08/14 18:13:28 jonas
  978. * adapted previous fix to Peter's asmsymbol patch
  979. Revision 1.22 2002/08/14 18:00:42 jonas
  980. * fixed tb0403
  981. Revision 1.21 2002/08/13 21:40:56 florian
  982. * more fixes for ppc calling conventions
  983. Revision 1.20 2002/08/11 14:32:26 peter
  984. * renamed current_library to objectlibrary
  985. Revision 1.19 2002/08/11 13:24:12 peter
  986. * saving of asmsymbols in ppu supported
  987. * asmsymbollist global is removed and moved into a new class
  988. tasmlibrarydata that will hold the info of a .a file which
  989. corresponds with a single module. Added librarydata to tmodule
  990. to keep the library info stored for the module. In the future the
  991. objectfiles will also be stored to the tasmlibrarydata class
  992. * all getlabel/newasmsymbol and friends are moved to the new class
  993. Revision 1.18 2002/08/06 20:55:21 florian
  994. * first part of ppc calling conventions fix
  995. Revision 1.17 2002/07/28 09:25:37 carl
  996. + correct size of parameter (64-bit portability)
  997. Revision 1.16 2002/07/27 19:53:51 jonas
  998. + generic implementation of tcg.g_flags2ref()
  999. * tcg.flags2xxx() now also needs a size parameter
  1000. Revision 1.15 2002/07/20 11:57:54 florian
  1001. * types.pas renamed to defbase.pas because D6 contains a types
  1002. unit so this would conflicts if D6 programms are compiled
  1003. + Willamette/SSE2 instructions to assembler added
  1004. Revision 1.14 2002/07/16 09:17:44 florian
  1005. * threadvar relocation result wasn't handled properly, it could cause
  1006. a crash
  1007. Revision 1.13 2002/07/11 14:41:28 florian
  1008. * start of the new generic parameter handling
  1009. Revision 1.12 2002/07/07 09:52:32 florian
  1010. * powerpc target fixed, very simple units can be compiled
  1011. * some basic stuff for better callparanode handling, far from being finished
  1012. Revision 1.11 2002/07/01 18:46:23 peter
  1013. * internal linker
  1014. * reorganized aasm layer
  1015. Revision 1.10 2002/07/01 16:23:53 peter
  1016. * cg64 patch
  1017. * basics for currency
  1018. * asnode updates for class and interface (not finished)
  1019. Revision 1.9 2002/05/20 13:30:40 carl
  1020. * bugfix of hdisponen (base must be set, not index)
  1021. * more portability fixes
  1022. }