ncgld.pas 50 KB

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