ncgld.pas 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053
  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,globals,
  41. symconst,symtype,symdef,symsym,symtable,defbase,paramgr,
  42. ncnv,ncon,nmem,
  43. aasmbase,aasmtai,aasmcpu,regvars,
  44. cginfo,cgbase,pass_2,
  45. cpubase,cpuinfo,cpupara,
  46. tgobj,ncgutil,cgobj,cg64f32,rgobj,rgcpu;
  47. {*****************************************************************************
  48. SecondLoad
  49. *****************************************************************************}
  50. procedure tcgloadnode.pass_2;
  51. var
  52. intreg,
  53. hregister : tregister;
  54. freereg : boolean;
  55. symtabletype : tsymtabletype;
  56. i : longint;
  57. href : treference;
  58. newsize : tcgsize;
  59. pushed : tpushedsaved;
  60. begin
  61. { we don't know the size of all arrays }
  62. newsize:=def_cgsize(resulttype.def);
  63. location_reset(location,LOC_REFERENCE,newsize);
  64. case symtableentry.typ of
  65. absolutesym :
  66. begin
  67. { this is only for toasm and toaddr }
  68. location.reference.symbol:=nil;
  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. hregister:=R_NO;
  94. { C variable }
  95. if (vo_is_C_var in tvarsym(symtableentry).varoptions) then
  96. begin
  97. location.reference.symbol:=objectlibrary.newasmsymbol(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.newasmsymbol(tvarsym(symtableentry).mangledname);
  104. cg.a_load_ref_reg(exprasmlist,OS_ADDR,location.reference,hregister);
  105. location.reference.symbol:=nil;
  106. location.reference.base:=hregister;
  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. { we've to allocate the register before we save the used registers }
  117. location.reference.base:=rg.getaddressregister(exprasmlist);
  118. rg.saveusedregisters(exprasmlist,pushed,[accumulator]);
  119. reference_reset_symbol(href,objectlibrary.newasmsymbol(tvarsym(symtableentry).mangledname),0);
  120. cg.a_param_ref(exprasmlist,OS_ADDR,href,paramanager.getintparaloc(1));
  121. { the called procedure isn't allowed to change }
  122. { any register except EAX }
  123. cg.a_call_name(exprasmlist,'FPC_RELOCATE_THREADVAR');
  124. cg.a_load_reg_reg(exprasmlist,OS_INT,accumulator,location.reference.base);
  125. rg.restoreusedregisters(exprasmlist,pushed);
  126. end
  127. { normal variable }
  128. else
  129. begin
  130. symtabletype:=symtable.symtabletype;
  131. { in case it is a register variable: }
  132. if tvarsym(symtableentry).reg<>R_NO then
  133. begin
  134. if tvarsym(symtableentry).reg in fpuregs then
  135. begin
  136. location_reset(location,LOC_CFPUREGISTER,def_cgsize(resulttype.def));
  137. location.register:=tvarsym(symtableentry).reg;
  138. end
  139. else
  140. begin
  141. intreg:=rg.makeregsize(tvarsym(symtableentry).reg,OS_INT);
  142. if (intreg in general_registers) and
  143. (not rg.regvar_loaded[intreg]) then
  144. load_regvar(exprasmlist,tvarsym(symtableentry));
  145. location_reset(location,LOC_CREGISTER,cg.reg_cgsize(tvarsym(symtableentry).reg));
  146. location.register:=tvarsym(symtableentry).reg;
  147. exclude(rg.unusedregsint,intreg);
  148. end;
  149. end
  150. else
  151. begin
  152. { first handle local and temporary variables }
  153. if (symtabletype in [parasymtable,inlinelocalsymtable,
  154. inlineparasymtable,localsymtable]) then
  155. begin
  156. location.reference.base:=procinfo.framepointer;
  157. if (symtabletype in [inlinelocalsymtable,
  158. localsymtable])
  159. {$ifdef powerpc}
  160. { the ifdef is only for speed reasons }
  161. and not(target_info.system in [system_powerpc_linux,system_powerpc_macos])
  162. {$endif powerpc}
  163. then
  164. location.reference.offset:=
  165. tvarsym(symtableentry).address-symtable.address_fixup
  166. else
  167. location.reference.offset:=
  168. tvarsym(symtableentry).address+symtable.address_fixup;
  169. {$ifndef powerpc}
  170. if (symtabletype in [localsymtable,inlinelocalsymtable]) then
  171. begin
  172. if use_esp_stackframe then
  173. dec(location.reference.offset,
  174. tvarsym(symtableentry).getvaluesize)
  175. else
  176. location.reference.offset:=-location.reference.offset;
  177. end;
  178. {$endif powerpc}
  179. if (lexlevel>symtable.symtablelevel) then
  180. begin
  181. hregister:=rg.getaddressregister(exprasmlist);
  182. { make a reference }
  183. reference_reset_base(href,procinfo.framepointer,procinfo.framepointer_offset);
  184. cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,hregister);
  185. { walk parents }
  186. i:=lexlevel-1;
  187. while (i>symtable.symtablelevel) do
  188. begin
  189. { make a reference }
  190. reference_reset_base(href,hregister,target_info.first_parm_offset);
  191. cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,hregister);
  192. dec(i);
  193. end;
  194. location.reference.base:=hregister;
  195. end;
  196. end
  197. else
  198. case symtabletype of
  199. globalsymtable,
  200. staticsymtable :
  201. begin
  202. location.reference.symbol:=objectlibrary.newasmsymbol(tvarsym(symtableentry).mangledname);
  203. end;
  204. stt_exceptsymtable:
  205. begin
  206. location.reference.base:=procinfo.framepointer;
  207. location.reference.offset:=tvarsym(symtableentry).address;
  208. end;
  209. objectsymtable:
  210. begin
  211. if (sp_static in tvarsym(symtableentry).symoptions) then
  212. location.reference.symbol:=objectlibrary.newasmsymbol(tvarsym(symtableentry).mangledname)
  213. else
  214. begin
  215. rg.getexplicitregisterint(exprasmlist,SELF_POINTER_REG);
  216. location.reference.base:=SELF_POINTER_REG;
  217. location.reference.offset:=tvarsym(symtableentry).address;
  218. end;
  219. end;
  220. withsymtable:
  221. begin
  222. if nf_islocal in tnode(twithsymtable(symtable).withnode).flags then
  223. location.reference:=twithnode(twithsymtable(symtable).withnode).withreference
  224. else
  225. begin
  226. location.reference.base:=rg.getaddressregister(exprasmlist);
  227. cg.a_load_ref_reg(exprasmlist,OS_ADDR,
  228. twithnode(twithsymtable(symtable).withnode).withreference,
  229. location.reference.base);
  230. end;
  231. inc(location.reference.offset,tvarsym(symtableentry).address);
  232. end;
  233. end;
  234. end;
  235. { in case call by reference, then calculate. Open array
  236. is always an reference! }
  237. if (tvarsym(symtableentry).varspez in [vs_var,vs_out]) or
  238. is_open_array(tvarsym(symtableentry).vartype.def) or
  239. is_array_of_const(tvarsym(symtableentry).vartype.def) or
  240. ((tvarsym(symtableentry).varspez=vs_const) and
  241. paramanager.push_addr_param(tvarsym(symtableentry).vartype.def)) then
  242. begin
  243. if hregister=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. location_reset(location,LOC_REFERENCE,newsize);
  249. location.reference.base:=hregister;
  250. end;
  251. end;
  252. end;
  253. procsym:
  254. begin
  255. if assigned(left) then
  256. begin
  257. {
  258. THIS IS A TERRIBLE HACK!!!!!! WHICH WILL NOT WORK
  259. ON 64-BIT SYSTEMS: SINCE PROCSYM FOR METHODS
  260. CONSISTS OF TWO OS_ADDR, so you cannot set it
  261. to OS_64 - how to solve?? Carl
  262. }
  263. if (sizeof(aword) = 4) then
  264. location_reset(location,LOC_CREFERENCE,OS_64)
  265. else
  266. internalerror(20020520);
  267. tg.gettempofsizereference(exprasmlist,2*POINTER_SIZE,location.reference);
  268. freereg:=false;
  269. { called as type.method, then we only need to return
  270. the address of the function, not the self pointer }
  271. if left.nodetype=typen then
  272. begin
  273. { there is no instance, we return 0 }
  274. cg.a_load_const_ref(exprasmlist,OS_ADDR,0,location.reference);
  275. end
  276. else
  277. begin
  278. secondpass(left);
  279. { load class instance address }
  280. case left.location.loc of
  281. LOC_CREGISTER,
  282. LOC_REGISTER:
  283. begin
  284. hregister:=left.location.register;
  285. if is_object(left.resulttype.def) then
  286. CGMessage(cg_e_illegal_expression);
  287. end;
  288. LOC_CREFERENCE,
  289. LOC_REFERENCE:
  290. begin
  291. hregister:=rg.getaddressregister(exprasmlist);
  292. if is_class_or_interface(left.resulttype.def) then
  293. cg.a_load_ref_reg(exprasmlist,OS_ADDR,left.location.reference,hregister)
  294. else
  295. cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,hregister);
  296. location_release(exprasmlist,left.location);
  297. location_freetemp(exprasmlist,left.location);
  298. end;
  299. else
  300. internalerror(26019);
  301. end;
  302. { store the class instance address }
  303. href:=location.reference;
  304. inc(href.offset,POINTER_SIZE);
  305. cg.a_load_reg_ref(exprasmlist,OS_ADDR,hregister,href);
  306. { hregister will be reused when loading a virtual method }
  307. freereg:=true;
  308. end;
  309. { virtual method ? }
  310. if (po_virtualmethod in tprocdef(resulttype.def).procoptions) then
  311. begin
  312. if not freereg then
  313. begin
  314. if left.nodetype <> typen then
  315. internalerror(200205161);
  316. reference_reset_symbol(href,objectlibrary.newasmsymbol(tobjectdef(left.resulttype.def).vmt_mangledname),
  317. tprocdef(resulttype.def)._class.vmtmethodoffset(tprocdef(resulttype.def).extnumber));
  318. end
  319. else
  320. begin
  321. { load vmt pointer }
  322. reference_reset_base(href,hregister,0);
  323. reference_release(exprasmlist,href);
  324. hregister:=rg.getaddressregister(exprasmlist);
  325. cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,hregister);
  326. reference_reset_base(href,hregister,tprocdef(resulttype.def)._class.vmtmethodoffset(
  327. tprocdef(resulttype.def).extnumber));
  328. reference_release(exprasmlist,href);
  329. end;
  330. { load method address }
  331. hregister:=rg.getaddressregister(exprasmlist);
  332. cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,hregister);
  333. { ... and store it }
  334. cg.a_load_reg_ref(exprasmlist,OS_ADDR,hregister,location.reference);
  335. rg.ungetaddressregister(exprasmlist,hregister);
  336. end
  337. else
  338. begin
  339. { we don't use the hregister }
  340. if freereg then
  341. rg.ungetregister(exprasmlist,hregister);
  342. { load address of the function }
  343. reference_reset_symbol(href,objectlibrary.newasmsymbol(tprocdef(resulttype.def).mangledname),0);
  344. hregister:=cg.get_scratch_reg_address(exprasmlist);
  345. cg.a_loadaddr_ref_reg(exprasmlist,href,hregister);
  346. cg.a_load_reg_ref(exprasmlist,OS_ADDR,hregister,location.reference);
  347. cg.free_scratch_reg(exprasmlist,hregister);
  348. end;
  349. end
  350. else
  351. begin
  352. {!!!!! Be aware, work on virtual methods too }
  353. location.reference.symbol:=objectlibrary.newasmsymbol(tprocdef(resulttype.def).mangledname);
  354. end;
  355. end;
  356. typedconstsym :
  357. begin
  358. location.reference.symbol:=objectlibrary.newasmsymbol(ttypedconstsym(symtableentry).mangledname);
  359. end;
  360. else internalerror(4);
  361. end;
  362. end;
  363. {*****************************************************************************
  364. SecondAssignment
  365. *****************************************************************************}
  366. procedure tcgassignmentnode.pass_2;
  367. var
  368. otlabel,hlabel,oflabel : tasmlabel;
  369. fputyp : tfloattype;
  370. href : treference;
  371. ai : taicpu;
  372. releaseright : boolean;
  373. pushedregs : tmaybesave;
  374. cgsize : tcgsize;
  375. begin
  376. otlabel:=truelabel;
  377. oflabel:=falselabel;
  378. objectlibrary.getlabel(truelabel);
  379. objectlibrary.getlabel(falselabel);
  380. {
  381. in most cases we can process first the right node which contains
  382. the most complex code. But not when the result is in the flags, then
  383. loading the left node afterwards can destroy the flags.
  384. when the right node returns as LOC_JUMP then we will generate
  385. the following code:
  386. rightnode
  387. true:
  388. leftnode
  389. assign 1
  390. false:
  391. leftnode
  392. assign 0
  393. }
  394. { Try to determine which side to calculate first, }
  395. if (right.location.loc<>LOC_FLAGS) and
  396. ((right.location.loc=LOC_JUMP) or
  397. (right.registers32>=left.registers32)) then
  398. begin
  399. secondpass(right);
  400. { increment source reference counter, this is
  401. useless for string constants}
  402. if (right.resulttype.def.needs_inittable) and
  403. (right.nodetype<>stringconstn) then
  404. cg.g_incrrefcount(exprasmlist,right.resulttype.def,right.location.reference);
  405. if codegenerror then
  406. exit;
  407. { We skip the generation of the left node when it's a jump, see
  408. explanation above }
  409. if (right.location.loc<>LOC_JUMP) and
  410. not(nf_concat_string in flags) then
  411. begin
  412. { left can't be never a 64 bit LOC_REGISTER, so the 3. arg }
  413. { can be false }
  414. maybe_save(exprasmlist,left.registers32,right.location,pushedregs);
  415. secondpass(left);
  416. { decrement destination reference counter }
  417. if (left.resulttype.def.needs_inittable) then
  418. cg.g_decrrefcount(exprasmlist,left.resulttype.def,left.location.reference);
  419. maybe_restore(exprasmlist,right.location,pushedregs);
  420. if codegenerror then
  421. exit;
  422. end;
  423. end
  424. else
  425. begin
  426. { calculate left sides }
  427. { don't do it yet if it's a crgister (JM) }
  428. if not(nf_concat_string in flags) then
  429. begin
  430. secondpass(left);
  431. { decrement destination reference counter }
  432. if (left.resulttype.def.needs_inittable) then
  433. cg.g_decrrefcount(exprasmlist,left.resulttype.def,left.location.reference);
  434. if codegenerror then
  435. exit;
  436. end;
  437. { left can't be never a 64 bit LOC_REGISTER, so the 3. arg }
  438. { can be false }
  439. maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
  440. secondpass(right);
  441. { increment source reference counter, this is
  442. useless for string constants}
  443. if (right.resulttype.def.needs_inittable) and
  444. (right.nodetype<>stringconstn) then
  445. cg.g_incrrefcount(exprasmlist,right.resulttype.def,right.location.reference);
  446. maybe_restore(exprasmlist,left.location,pushedregs);
  447. if codegenerror then
  448. exit;
  449. end;
  450. if not(left.location.loc in [LOC_REFERENCE,LOC_CFPUREGISTER,
  451. {$ifdef SUPPORT_MMX}LOC_CMMXREGISTER,{$endif}
  452. LOC_CREGISTER]) then
  453. begin
  454. CGMessage(cg_e_illegal_expression);
  455. exit;
  456. end;
  457. releaseright:=true;
  458. { shortstring assignments are handled separately }
  459. if is_shortstring(left.resulttype.def) then
  460. begin
  461. {
  462. we can get here only in the following situations
  463. for the right node:
  464. - empty constant string
  465. - char
  466. }
  467. { empty constant string }
  468. if (right.nodetype=stringconstn) and
  469. (tstringconstnode(right).len=0) then
  470. begin
  471. cg.a_load_const_ref(exprasmlist,OS_8,0,left.location.reference);
  472. end
  473. { char loading }
  474. else if is_char(right.resulttype.def) then
  475. begin
  476. if right.nodetype=ordconstn then
  477. begin
  478. if (target_info.endian = endian_little) then
  479. cg.a_load_const_ref(exprasmlist,OS_16,(tordconstnode(right).value shl 8) or 1,
  480. left.location.reference)
  481. else
  482. cg.a_load_const_ref(exprasmlist,OS_16,tordconstnode(right).value or (1 shl 8),
  483. left.location.reference);
  484. end
  485. else
  486. begin
  487. href:=left.location.reference;
  488. cg.a_load_const_ref(exprasmlist,OS_8,1,href);
  489. inc(href.offset,1);
  490. case right.location.loc of
  491. LOC_REGISTER,
  492. LOC_CREGISTER :
  493. cg.a_load_reg_ref(exprasmlist,OS_8,rg.makeregsize(right.location.register,OS_8),href);
  494. LOC_REFERENCE,
  495. LOC_CREFERENCE :
  496. cg.a_load_ref_ref(exprasmlist,OS_8,right.location.reference,href);
  497. else
  498. internalerror(200205111);
  499. end;
  500. end;
  501. end
  502. else
  503. internalerror(200204249);
  504. end
  505. else
  506. begin
  507. case right.location.loc of
  508. LOC_CONSTANT :
  509. begin
  510. if right.location.size in [OS_64,OS_S64] then
  511. cg64.a_load64_const_loc(exprasmlist,
  512. right.location.valueqword,left.location)
  513. else
  514. cg.a_load_const_loc(exprasmlist,right.location.value,left.location);
  515. end;
  516. LOC_REFERENCE,
  517. LOC_CREFERENCE :
  518. begin
  519. case left.location.loc of
  520. LOC_CREGISTER :
  521. begin
  522. cgsize:=def_cgsize(left.resulttype.def);
  523. if cgsize in [OS_64,OS_S64] then
  524. cg64.a_load64_ref_reg(exprasmlist,
  525. right.location.reference,left.location.register64)
  526. else
  527. cg.a_load_ref_reg(exprasmlist,cgsize,
  528. right.location.reference,left.location.register);
  529. location_release(exprasmlist,right.location);
  530. end;
  531. LOC_CFPUREGISTER :
  532. begin
  533. cg.a_loadfpu_ref_reg(exprasmlist,
  534. def_cgsize(right.resulttype.def),
  535. right.location.reference,
  536. left.location.register);
  537. end;
  538. LOC_REFERENCE,
  539. LOC_CREFERENCE :
  540. begin
  541. cg.g_concatcopy(exprasmlist,right.location.reference,
  542. left.location.reference,left.resulttype.def.size,true,false);
  543. { right.location is already released by concatcopy }
  544. releaseright:=false;
  545. end;
  546. else
  547. internalerror(200203284);
  548. end;
  549. end;
  550. {$ifdef SUPPORT_MMX}
  551. LOC_CMMXREGISTER,
  552. LOC_MMXREGISTER:
  553. begin
  554. if left.location.loc=LOC_CMMXREGISTER then
  555. cg.a_loadmm_reg_reg(exprasmlist,right.location.register,left.location.register)
  556. else
  557. cg.a_loadmm_reg_ref(exprasmlist,right.location.register,left.location.reference);
  558. end;
  559. {$endif SUPPORT_MMX}
  560. LOC_REGISTER,
  561. LOC_CREGISTER :
  562. begin
  563. cgsize:=def_cgsize(left.resulttype.def);
  564. if cgsize in [OS_64,OS_S64] then
  565. cg64.a_load64_reg_loc(exprasmlist,
  566. right.location.register64,left.location)
  567. else
  568. cg.a_load_reg_loc(exprasmlist,right.location.size,right.location.register,left.location);
  569. end;
  570. LOC_FPUREGISTER,LOC_CFPUREGISTER :
  571. begin
  572. if (left.resulttype.def.deftype=floatdef) then
  573. fputyp:=tfloatdef(left.resulttype.def).typ
  574. else
  575. if (right.resulttype.def.deftype=floatdef) then
  576. fputyp:=tfloatdef(right.resulttype.def).typ
  577. else
  578. if (right.nodetype=typeconvn) and
  579. (ttypeconvnode(right).left.resulttype.def.deftype=floatdef) then
  580. fputyp:=tfloatdef(ttypeconvnode(right).left.resulttype.def).typ
  581. else
  582. fputyp:=s32real;
  583. cg.a_loadfpu_reg_loc(exprasmlist,
  584. tfloat2tcgsize[fputyp],
  585. right.location.register,left.location);
  586. end;
  587. LOC_JUMP :
  588. begin
  589. cgsize:=def_cgsize(left.resulttype.def);
  590. objectlibrary.getlabel(hlabel);
  591. { generate the leftnode for the true case, and
  592. release the location }
  593. cg.a_label(exprasmlist,truelabel);
  594. maybe_save(exprasmlist,left.registers32,right.location,pushedregs);
  595. secondpass(left);
  596. maybe_restore(exprasmlist,right.location,pushedregs);
  597. if codegenerror then
  598. exit;
  599. cg.a_load_const_loc(exprasmlist,1,left.location);
  600. location_release(exprasmlist,left.location);
  601. cg.a_jmp_always(exprasmlist,hlabel);
  602. { generate the leftnode for the false case }
  603. cg.a_label(exprasmlist,falselabel);
  604. maybe_save(exprasmlist,left.registers32,right.location,pushedregs);
  605. secondpass(left);
  606. maybe_restore(exprasmlist,right.location,pushedregs);
  607. if codegenerror then
  608. exit;
  609. cg.a_load_const_loc(exprasmlist,0,left.location);
  610. cg.a_label(exprasmlist,hlabel);
  611. end;
  612. LOC_FLAGS :
  613. begin
  614. // this can be a wordbool or longbool too, no?
  615. if left.location.loc=LOC_CREGISTER then
  616. cg.g_flags2reg(exprasmlist,def_cgsize(left.resulttype.def),right.location.resflags,left.location.register)
  617. else
  618. begin
  619. if not(left.location.loc = LOC_REFERENCE) then
  620. internalerror(200203273);
  621. cg.g_flags2ref(exprasmlist,def_cgsize(left.resulttype.def),right.location.resflags,left.location.reference);
  622. end;
  623. end;
  624. end;
  625. end;
  626. if releaseright then
  627. location_release(exprasmlist,right.location);
  628. location_release(exprasmlist,left.location);
  629. truelabel:=otlabel;
  630. falselabel:=oflabel;
  631. end;
  632. {*****************************************************************************
  633. SecondFuncRet
  634. *****************************************************************************}
  635. procedure tcgfuncretnode.pass_2;
  636. var
  637. hreg : tregister;
  638. href : treference;
  639. pp : tprocinfo;
  640. hr_valid : boolean;
  641. i : integer;
  642. begin
  643. location_reset(location,LOC_REFERENCE,def_cgsize(resulttype.def));
  644. hr_valid:=false;
  645. if (not inlining_procedure) and
  646. (lexlevel<>funcretsym.owner.symtablelevel) then
  647. begin
  648. hreg:=rg.getaddressregister(exprasmlist);
  649. hr_valid:=true;
  650. reference_reset_base(href,procinfo.framepointer,procinfo.framepointer_offset);
  651. cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,hreg);
  652. { walk up the stack frame }
  653. pp:=procinfo.parent;
  654. i:=lexlevel-1;
  655. while i>funcretsym.owner.symtablelevel do
  656. begin
  657. reference_reset_base(href,hreg,pp.framepointer_offset);
  658. cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,hreg);
  659. pp:=pp.parent;
  660. dec(i);
  661. end;
  662. location.reference.base:=hreg;
  663. location.reference.offset:=pp.return_offset;
  664. end
  665. else
  666. begin
  667. location.reference.base:=procinfo.framepointer;
  668. location.reference.offset:=procinfo.return_offset;
  669. end;
  670. if paramanager.ret_in_param(resulttype.def) then
  671. begin
  672. { the parameter is actual a pointer to the value }
  673. if not hr_valid then
  674. hreg:=rg.getaddressregister(exprasmlist);
  675. cg.a_load_ref_reg(exprasmlist,OS_ADDR,location.reference,hreg);
  676. location.reference.base:=hreg;
  677. location.reference.offset:=0;
  678. end;
  679. end;
  680. {*****************************************************************************
  681. SecondArrayConstruct
  682. *****************************************************************************}
  683. const
  684. vtInteger = 0;
  685. vtBoolean = 1;
  686. vtChar = 2;
  687. vtExtended = 3;
  688. vtString = 4;
  689. vtPointer = 5;
  690. vtPChar = 6;
  691. vtObject = 7;
  692. vtClass = 8;
  693. vtWideChar = 9;
  694. vtPWideChar = 10;
  695. vtAnsiString = 11;
  696. vtCurrency = 12;
  697. vtVariant = 13;
  698. vtInterface = 14;
  699. vtWideString = 15;
  700. vtInt64 = 16;
  701. vtQWord = 17;
  702. procedure tcgarrayconstructornode.pass_2;
  703. var
  704. hp : tarrayconstructornode;
  705. href : treference;
  706. lt : tdef;
  707. vaddr : boolean;
  708. vtype : longint;
  709. freetemp,
  710. dovariant : boolean;
  711. elesize : longint;
  712. tmpreg : tregister;
  713. begin
  714. dovariant:=(nf_forcevaria in flags) or tarraydef(resulttype.def).isvariant;
  715. if dovariant then
  716. elesize:=8
  717. else
  718. elesize:=tarraydef(resulttype.def).elesize;
  719. if not(nf_cargs in flags) then
  720. begin
  721. location_reset(location,LOC_REFERENCE,OS_NO);
  722. { Allocate always a temp, also if no elements are required, to
  723. be sure that location is valid (PFV) }
  724. if tarraydef(resulttype.def).highrange=-1 then
  725. tg.gettempofsizereference(exprasmlist,elesize,location.reference)
  726. else
  727. tg.gettempofsizereference(exprasmlist,(tarraydef(resulttype.def).highrange+1)*elesize,location.reference);
  728. href:=location.reference;
  729. end;
  730. hp:=self;
  731. while assigned(hp) do
  732. begin
  733. if assigned(hp.left) then
  734. begin
  735. freetemp:=true;
  736. secondpass(hp.left);
  737. if codegenerror then
  738. exit;
  739. if dovariant then
  740. begin
  741. { find the correct vtype value }
  742. vtype:=$ff;
  743. vaddr:=false;
  744. lt:=hp.left.resulttype.def;
  745. case lt.deftype of
  746. enumdef,
  747. orddef :
  748. begin
  749. if is_64bitint(lt) then
  750. begin
  751. case torddef(lt).typ of
  752. s64bit:
  753. vtype:=vtInt64;
  754. u64bit:
  755. vtype:=vtQWord;
  756. end;
  757. freetemp:=false;
  758. vaddr:=true;
  759. end
  760. else if (lt.deftype=enumdef) or
  761. is_integer(lt) then
  762. vtype:=vtInteger
  763. else
  764. if is_boolean(lt) then
  765. vtype:=vtBoolean
  766. else
  767. if (lt.deftype=orddef) and (torddef(lt).typ=uchar) then
  768. vtype:=vtChar;
  769. end;
  770. floatdef :
  771. begin
  772. vtype:=vtExtended;
  773. vaddr:=true;
  774. freetemp:=false;
  775. end;
  776. procvardef,
  777. pointerdef :
  778. begin
  779. if is_pchar(lt) then
  780. vtype:=vtPChar
  781. else
  782. vtype:=vtPointer;
  783. end;
  784. classrefdef :
  785. vtype:=vtClass;
  786. objectdef :
  787. begin
  788. vtype:=vtObject;
  789. end;
  790. stringdef :
  791. begin
  792. if is_shortstring(lt) then
  793. begin
  794. vtype:=vtString;
  795. vaddr:=true;
  796. freetemp:=false;
  797. end
  798. else
  799. if is_ansistring(lt) then
  800. begin
  801. vtype:=vtAnsiString;
  802. freetemp:=false;
  803. end
  804. else
  805. if is_widestring(lt) then
  806. begin
  807. vtype:=vtWideString;
  808. freetemp:=false;
  809. end;
  810. end;
  811. end;
  812. if vtype=$ff then
  813. internalerror(14357);
  814. { write C style pushes or an pascal array }
  815. if nf_cargs in flags then
  816. begin
  817. if vaddr then
  818. begin
  819. location_force_mem(exprasmlist,hp.left.location);
  820. cg.a_paramaddr_ref(exprasmlist,hp.left.location.reference,paralocdummy);
  821. location_release(exprasmlist,hp.left.location);
  822. if freetemp then
  823. location_freetemp(exprasmlist,hp.left.location);
  824. end
  825. else
  826. cg.a_param_loc(exprasmlist,hp.left.location,paralocdummy);
  827. inc(pushedparasize,pointer_size);
  828. end
  829. else
  830. begin
  831. { write changing field update href to the next element }
  832. inc(href.offset,4);
  833. if vaddr then
  834. begin
  835. location_force_mem(exprasmlist,hp.left.location);
  836. tmpreg:=cg.get_scratch_reg_address(exprasmlist);
  837. cg.a_loadaddr_ref_reg(exprasmlist,hp.left.location.reference,tmpreg);
  838. cg.a_load_reg_ref(exprasmlist,cg.reg_cgsize(tmpreg),tmpreg,href);
  839. cg.free_scratch_reg(exprasmlist,tmpreg);
  840. location_release(exprasmlist,hp.left.location);
  841. if freetemp then
  842. location_freetemp(exprasmlist,hp.left.location);
  843. end
  844. else
  845. begin
  846. location_release(exprasmlist,left.location);
  847. cg.a_load_loc_ref(exprasmlist,hp.left.location,href);
  848. end;
  849. { update href to the vtype field and write it }
  850. dec(href.offset,4);
  851. cg.a_load_const_ref(exprasmlist, OS_INT,vtype,href);
  852. { goto next array element }
  853. inc(href.offset,8);
  854. end;
  855. end
  856. else
  857. { normal array constructor of the same type }
  858. begin
  859. case elesize of
  860. 1,2,4 :
  861. begin
  862. location_release(exprasmlist,left.location);
  863. cg.a_load_loc_ref(exprasmlist,hp.left.location,href);
  864. end;
  865. 8 :
  866. begin
  867. if hp.left.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
  868. cg64.a_load64_loc_ref(exprasmlist,hp.left.location,href)
  869. else
  870. cg.g_concatcopy(exprasmlist,hp.left.location.reference,href,elesize,freetemp,false);
  871. end;
  872. else
  873. begin
  874. { concatcopy only supports reference }
  875. if not(hp.left.location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) then
  876. internalerror(200108012);
  877. cg.g_concatcopy(exprasmlist,hp.left.location.reference,href,elesize,freetemp,false);
  878. end;
  879. end;
  880. inc(href.offset,elesize);
  881. end;
  882. end;
  883. { load next entry }
  884. hp:=tarrayconstructornode(hp.right);
  885. end;
  886. end;
  887. begin
  888. cloadnode:=tcgloadnode;
  889. cassignmentnode:=tcgassignmentnode;
  890. cfuncretnode:=tcgfuncretnode;
  891. carrayconstructornode:=tcgarrayconstructornode;
  892. end.
  893. {
  894. $Log$
  895. Revision 1.24 2002-08-17 09:23:35 florian
  896. * first part of procinfo rewrite
  897. Revision 1.23 2002/08/14 18:13:28 jonas
  898. * adapted previous fix to Peter's asmsymbol patch
  899. Revision 1.22 2002/08/14 18:00:42 jonas
  900. * fixed tb0403
  901. Revision 1.21 2002/08/13 21:40:56 florian
  902. * more fixes for ppc calling conventions
  903. Revision 1.20 2002/08/11 14:32:26 peter
  904. * renamed current_library to objectlibrary
  905. Revision 1.19 2002/08/11 13:24:12 peter
  906. * saving of asmsymbols in ppu supported
  907. * asmsymbollist global is removed and moved into a new class
  908. tasmlibrarydata that will hold the info of a .a file which
  909. corresponds with a single module. Added librarydata to tmodule
  910. to keep the library info stored for the module. In the future the
  911. objectfiles will also be stored to the tasmlibrarydata class
  912. * all getlabel/newasmsymbol and friends are moved to the new class
  913. Revision 1.18 2002/08/06 20:55:21 florian
  914. * first part of ppc calling conventions fix
  915. Revision 1.17 2002/07/28 09:25:37 carl
  916. + correct size of parameter (64-bit portability)
  917. Revision 1.16 2002/07/27 19:53:51 jonas
  918. + generic implementation of tcg.g_flags2ref()
  919. * tcg.flags2xxx() now also needs a size parameter
  920. Revision 1.15 2002/07/20 11:57:54 florian
  921. * types.pas renamed to defbase.pas because D6 contains a types
  922. unit so this would conflicts if D6 programms are compiled
  923. + Willamette/SSE2 instructions to assembler added
  924. Revision 1.14 2002/07/16 09:17:44 florian
  925. * threadvar relocation result wasn't handled properly, it could cause
  926. a crash
  927. Revision 1.13 2002/07/11 14:41:28 florian
  928. * start of the new generic parameter handling
  929. Revision 1.12 2002/07/07 09:52:32 florian
  930. * powerpc target fixed, very simple units can be compiled
  931. * some basic stuff for better callparanode handling, far from being finished
  932. Revision 1.11 2002/07/01 18:46:23 peter
  933. * internal linker
  934. * reorganized aasm layer
  935. Revision 1.10 2002/07/01 16:23:53 peter
  936. * cg64 patch
  937. * basics for currency
  938. * asnode updates for class and interface (not finished)
  939. Revision 1.9 2002/05/20 13:30:40 carl
  940. * bugfix of hdisponen (base must be set, not index)
  941. * more portability fixes
  942. Revision 1.8 2002/05/18 13:34:09 peter
  943. * readded missing revisions
  944. Revision 1.7 2002/05/18 11:17:03 peter
  945. * fixed internalerror due to releasing an not initialized register
  946. Revision 1.6 2002/05/16 19:46:37 carl
  947. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  948. + try to fix temp allocation (still in ifdef)
  949. + generic constructor calls
  950. + start of tassembler / tmodulebase class cleanup
  951. Revision 1.5 2002/05/14 19:34:42 peter
  952. * removed old logs and updated copyright year
  953. Revision 1.4 2002/05/13 19:54:37 peter
  954. * removed n386ld and n386util units
  955. * maybe_save/maybe_restore added instead of the old maybe_push
  956. Revision 1.3 2002/05/12 16:53:07 peter
  957. * moved entry and exitcode to ncgutil and cgobj
  958. * foreach gets extra argument for passing local data to the
  959. iterator function
  960. * -CR checks also class typecasts at runtime by changing them
  961. into as
  962. * fixed compiler to cycle with the -CR option
  963. * fixed stabs with elf writer, finally the global variables can
  964. be watched
  965. * removed a lot of routines from cga unit and replaced them by
  966. calls to cgobj
  967. * u32bit-s32bit updates for and,or,xor nodes. When one element is
  968. u32bit then the other is typecasted also to u32bit without giving
  969. a rangecheck warning/error.
  970. * fixed pascal calling method with reversing also the high tree in
  971. the parast, detected by tcalcst3 test
  972. Revision 1.2 2002/04/21 15:24:38 carl
  973. + a_jmp_cond -> a_jmp_always (a_jmp_cond is NOT portable)
  974. + changeregsize -> rg.makeregsize
  975. Revision 1.1 2002/04/19 15:39:34 peter
  976. * removed some more routines from cga
  977. * moved location_force_reg/mem to ncgutil
  978. * moved arrayconstructnode secondpass to ncgld
  979. }