ncgld.pas 50 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179
  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 tprocdef(resulttype.def).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,tprocdef(resulttype.def)._class.vmtmethodoffset(
  332. tprocdef(resulttype.def).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(tprocdef(resulttype.def).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(tprocdef(resulttype.def).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. releaseright : boolean;
  383. pushedregs : tmaybesave;
  384. cgsize : tcgsize;
  385. r:Tregister;
  386. begin
  387. location_reset(location,LOC_VOID,OS_NO);
  388. otlabel:=truelabel;
  389. oflabel:=falselabel;
  390. objectlibrary.getlabel(truelabel);
  391. objectlibrary.getlabel(falselabel);
  392. {
  393. in most cases we can process first the right node which contains
  394. the most complex code. But not when the result is in the flags, then
  395. loading the left node afterwards can destroy the flags.
  396. when the right node returns as LOC_JUMP then we will generate
  397. the following code:
  398. rightnode
  399. true:
  400. leftnode
  401. assign 1
  402. false:
  403. leftnode
  404. assign 0
  405. }
  406. { Try to determine which side to calculate first, }
  407. if (right.expectloc<>LOC_FLAGS) and
  408. ((right.expectloc=LOC_JUMP) or
  409. (right.nodetype=calln) or
  410. (right.registers32>=left.registers32)) then
  411. begin
  412. secondpass(right);
  413. { increment source reference counter, this is
  414. useless for string constants}
  415. if (right.resulttype.def.needs_inittable) and
  416. (right.nodetype<>stringconstn) then
  417. cg.g_incrrefcount(exprasmlist,right.resulttype.def,right.location.reference);
  418. if codegenerror then
  419. exit;
  420. { We skip the generation of the left node when it's a jump, see
  421. explanation above }
  422. if (right.location.loc<>LOC_JUMP) and
  423. not(nf_concat_string in flags) then
  424. begin
  425. { left can't be never a 64 bit LOC_REGISTER, so the 3. arg }
  426. { can be false }
  427. {$ifndef newra}
  428. maybe_save(exprasmlist,left.registers32,right.location,pushedregs);
  429. {$endif}
  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. {$ifndef newra}
  435. maybe_restore(exprasmlist,right.location,pushedregs);
  436. {$endif newra}
  437. if codegenerror then
  438. exit;
  439. end;
  440. end
  441. else
  442. begin
  443. { calculate left sides }
  444. { don't do it yet if it's a crgister (JM) }
  445. if not(nf_concat_string in flags) then
  446. begin
  447. secondpass(left);
  448. { decrement destination reference counter }
  449. if (left.resulttype.def.needs_inittable) then
  450. cg.g_decrrefcount(exprasmlist,left.resulttype.def,left.location.reference);
  451. if codegenerror then
  452. exit;
  453. end;
  454. { left can't be never a 64 bit LOC_REGISTER, so the 3. arg }
  455. { can be false }
  456. {$ifndef newra}
  457. maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
  458. {$endif newra}
  459. secondpass(right);
  460. { increment source reference counter, this is
  461. useless for string constants}
  462. if (right.resulttype.def.needs_inittable) and
  463. (right.nodetype<>stringconstn) then
  464. cg.g_incrrefcount(exprasmlist,right.resulttype.def,right.location.reference);
  465. {$ifndef newra}
  466. maybe_restore(exprasmlist,left.location,pushedregs);
  467. {$endif}
  468. if codegenerror then
  469. exit;
  470. end;
  471. releaseright:=true;
  472. { shortstring assignments are handled separately }
  473. if is_shortstring(left.resulttype.def) then
  474. begin
  475. {
  476. we can get here only in the following situations
  477. for the right node:
  478. - empty constant string
  479. - char
  480. }
  481. { empty constant string }
  482. if (right.nodetype=stringconstn) and
  483. (tstringconstnode(right).len=0) then
  484. begin
  485. cg.a_load_const_ref(exprasmlist,OS_8,0,left.location.reference);
  486. end
  487. { char loading }
  488. else if is_char(right.resulttype.def) then
  489. begin
  490. if right.nodetype=ordconstn then
  491. begin
  492. if (target_info.endian = endian_little) then
  493. cg.a_load_const_ref(exprasmlist,OS_16,(tordconstnode(right).value shl 8) or 1,
  494. left.location.reference)
  495. else
  496. cg.a_load_const_ref(exprasmlist,OS_16,tordconstnode(right).value or (1 shl 8),
  497. left.location.reference);
  498. end
  499. else
  500. begin
  501. href:=left.location.reference;
  502. cg.a_load_const_ref(exprasmlist,OS_8,1,href);
  503. inc(href.offset,1);
  504. case right.location.loc of
  505. LOC_REGISTER,
  506. LOC_CREGISTER :
  507. begin
  508. r.enum:=R_INTREGISTER;
  509. r.number:=(right.location.register.number and not $ff) or R_SUBL;
  510. cg.a_load_reg_ref(exprasmlist,OS_8,r,href);
  511. end;
  512. LOC_REFERENCE,
  513. LOC_CREFERENCE :
  514. cg.a_load_ref_ref(exprasmlist,OS_8,right.location.reference,href);
  515. else
  516. internalerror(200205111);
  517. end;
  518. end;
  519. end
  520. else
  521. internalerror(200204249);
  522. end
  523. else
  524. begin
  525. case right.location.loc of
  526. LOC_CONSTANT :
  527. begin
  528. if right.location.size in [OS_64,OS_S64] then
  529. cg64.a_load64_const_loc(exprasmlist,
  530. right.location.valueqword,left.location)
  531. else
  532. cg.a_load_const_loc(exprasmlist,right.location.value,left.location);
  533. end;
  534. LOC_REFERENCE,
  535. LOC_CREFERENCE :
  536. begin
  537. case left.location.loc of
  538. LOC_CREGISTER :
  539. begin
  540. cgsize:=def_cgsize(left.resulttype.def);
  541. if cgsize in [OS_64,OS_S64] then
  542. cg64.a_load64_ref_reg(exprasmlist,
  543. right.location.reference,left.location.register64)
  544. else
  545. cg.a_load_ref_reg(exprasmlist,cgsize,
  546. right.location.reference,left.location.register);
  547. location_release(exprasmlist,right.location);
  548. end;
  549. LOC_CFPUREGISTER :
  550. begin
  551. cg.a_loadfpu_ref_reg(exprasmlist,
  552. def_cgsize(right.resulttype.def),
  553. right.location.reference,
  554. left.location.register);
  555. end;
  556. LOC_REFERENCE,
  557. LOC_CREFERENCE :
  558. begin
  559. cg.g_concatcopy(exprasmlist,right.location.reference,
  560. left.location.reference,left.resulttype.def.size,true,false);
  561. { right.location is already released by concatcopy }
  562. releaseright:=false;
  563. end;
  564. else
  565. internalerror(200203284);
  566. end;
  567. end;
  568. {$ifdef SUPPORT_MMX}
  569. LOC_CMMXREGISTER,
  570. LOC_MMXREGISTER:
  571. begin
  572. if left.location.loc=LOC_CMMXREGISTER then
  573. cg.a_loadmm_reg_reg(exprasmlist,right.location.register,left.location.register)
  574. else
  575. cg.a_loadmm_reg_ref(exprasmlist,right.location.register,left.location.reference);
  576. end;
  577. {$endif SUPPORT_MMX}
  578. LOC_REGISTER,
  579. LOC_CREGISTER :
  580. begin
  581. cgsize:=def_cgsize(left.resulttype.def);
  582. if cgsize in [OS_64,OS_S64] then
  583. cg64.a_load64_reg_loc(exprasmlist,
  584. right.location.register64,left.location)
  585. else
  586. cg.a_load_reg_loc(exprasmlist,right.location.size,right.location.register,left.location);
  587. end;
  588. LOC_FPUREGISTER,LOC_CFPUREGISTER :
  589. begin
  590. if (left.resulttype.def.deftype=floatdef) then
  591. fputyp:=tfloatdef(left.resulttype.def).typ
  592. else
  593. if (right.resulttype.def.deftype=floatdef) then
  594. fputyp:=tfloatdef(right.resulttype.def).typ
  595. else
  596. if (right.nodetype=typeconvn) and
  597. (ttypeconvnode(right).left.resulttype.def.deftype=floatdef) then
  598. fputyp:=tfloatdef(ttypeconvnode(right).left.resulttype.def).typ
  599. else
  600. fputyp:=s32real;
  601. cg.a_loadfpu_reg_loc(exprasmlist,
  602. tfloat2tcgsize[fputyp],
  603. right.location.register,left.location);
  604. end;
  605. LOC_JUMP :
  606. begin
  607. cgsize:=def_cgsize(left.resulttype.def);
  608. objectlibrary.getlabel(hlabel);
  609. { generate the leftnode for the true case, and
  610. release the location }
  611. cg.a_label(exprasmlist,truelabel);
  612. {$ifndef newra}
  613. maybe_save(exprasmlist,left.registers32,right.location,pushedregs);
  614. {$endif newra}
  615. secondpass(left);
  616. {$ifndef newra}
  617. maybe_restore(exprasmlist,right.location,pushedregs);
  618. {$endif newra}
  619. if codegenerror then
  620. exit;
  621. cg.a_load_const_loc(exprasmlist,1,left.location);
  622. location_release(exprasmlist,left.location);
  623. cg.a_jmp_always(exprasmlist,hlabel);
  624. { generate the leftnode for the false case }
  625. cg.a_label(exprasmlist,falselabel);
  626. {$ifndef newra}
  627. maybe_save(exprasmlist,left.registers32,right.location,pushedregs);
  628. {$endif}
  629. include(left.flags,nf_allow_multi_pass2);
  630. secondpass(left);
  631. {$ifndef newra}
  632. maybe_restore(exprasmlist,right.location,pushedregs);
  633. {$endif newra}
  634. if codegenerror then
  635. exit;
  636. cg.a_load_const_loc(exprasmlist,0,left.location);
  637. cg.a_label(exprasmlist,hlabel);
  638. end;
  639. {$ifdef cpuflags}
  640. LOC_FLAGS :
  641. begin
  642. {This can be a wordbool or longbool too, no?}
  643. if left.location.loc=LOC_CREGISTER then
  644. cg.g_flags2reg(exprasmlist,def_cgsize(left.resulttype.def),right.location.resflags,left.location.register)
  645. else
  646. begin
  647. if not(left.location.loc = LOC_REFERENCE) then
  648. internalerror(200203273);
  649. cg.g_flags2ref(exprasmlist,def_cgsize(left.resulttype.def),right.location.resflags,left.location.reference);
  650. end;
  651. end;
  652. {$endif cpuflags}
  653. end;
  654. end;
  655. if releaseright then
  656. location_release(exprasmlist,right.location);
  657. location_release(exprasmlist,left.location);
  658. truelabel:=otlabel;
  659. falselabel:=oflabel;
  660. end;
  661. {*****************************************************************************
  662. SecondFuncRet
  663. *****************************************************************************}
  664. procedure tcgfuncretnode.pass_2;
  665. var
  666. hreg : tregister;
  667. href : treference;
  668. pp : tprocinfo;
  669. hr_valid : boolean;
  670. i : integer;
  671. begin
  672. location_reset(location,LOC_REFERENCE,def_cgsize(resulttype.def));
  673. hr_valid:=false;
  674. if (not inlining_procedure) and
  675. (lexlevel<>funcretsym.owner.symtablelevel) then
  676. begin
  677. hreg:=rg.getaddressregister(exprasmlist);
  678. hr_valid:=true;
  679. reference_reset_base(href,procinfo.framepointer,procinfo.framepointer_offset);
  680. cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,hreg);
  681. { walk up the stack frame }
  682. pp:=procinfo.parent;
  683. i:=lexlevel-1;
  684. while i>funcretsym.owner.symtablelevel do
  685. begin
  686. reference_reset_base(href,hreg,pp.framepointer_offset);
  687. cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,hreg);
  688. pp:=pp.parent;
  689. dec(i);
  690. end;
  691. location.reference.base:=hreg;
  692. location.reference.offset:=pp.return_offset;
  693. end
  694. else
  695. begin
  696. location.reference.base:=procinfo.framepointer;
  697. location.reference.offset:=procinfo.return_offset;
  698. end;
  699. if paramanager.ret_in_param(funcretsym.returntype.def,
  700. tprocdef(funcretsym.owner.defowner).proccalloption) then
  701. begin
  702. { the parameter is actual a pointer to the value }
  703. if not hr_valid then
  704. hreg:=rg.getaddressregister(exprasmlist);
  705. cg.a_load_ref_reg(exprasmlist,OS_ADDR,location.reference,hreg);
  706. location.reference.base:=hreg;
  707. location.reference.offset:=0;
  708. end;
  709. end;
  710. {*****************************************************************************
  711. SecondArrayConstruct
  712. *****************************************************************************}
  713. const
  714. vtInteger = 0;
  715. vtBoolean = 1;
  716. vtChar = 2;
  717. vtExtended = 3;
  718. vtString = 4;
  719. vtPointer = 5;
  720. vtPChar = 6;
  721. vtObject = 7;
  722. vtClass = 8;
  723. vtWideChar = 9;
  724. vtPWideChar = 10;
  725. vtAnsiString = 11;
  726. vtCurrency = 12;
  727. vtVariant = 13;
  728. vtInterface = 14;
  729. vtWideString = 15;
  730. vtInt64 = 16;
  731. vtQWord = 17;
  732. procedure tcgarrayconstructornode.pass_2;
  733. var
  734. hp : tarrayconstructornode;
  735. href : treference;
  736. lt : tdef;
  737. vaddr : boolean;
  738. vtype : longint;
  739. freetemp,
  740. dovariant : boolean;
  741. elesize : longint;
  742. tmpreg : tregister;
  743. begin
  744. dovariant:=(nf_forcevaria in flags) or tarraydef(resulttype.def).isvariant;
  745. if dovariant then
  746. elesize:=8
  747. else
  748. elesize:=tarraydef(resulttype.def).elesize;
  749. if nf_cargs in flags then
  750. location_reset(location,LOC_VOID,OS_NO)
  751. else
  752. location_reset(location,LOC_CREFERENCE,OS_NO);
  753. if not(nf_cargs in flags) then
  754. begin
  755. { Allocate always a temp, also if no elements are required, to
  756. be sure that location is valid (PFV) }
  757. if tarraydef(resulttype.def).highrange=-1 then
  758. tg.GetTemp(exprasmlist,elesize,tt_normal,location.reference)
  759. else
  760. tg.GetTemp(exprasmlist,(tarraydef(resulttype.def).highrange+1)*elesize,tt_normal,location.reference);
  761. href:=location.reference;
  762. end;
  763. hp:=self;
  764. while assigned(hp) do
  765. begin
  766. if assigned(hp.left) then
  767. begin
  768. freetemp:=true;
  769. secondpass(hp.left);
  770. if codegenerror then
  771. exit;
  772. if dovariant then
  773. begin
  774. { find the correct vtype value }
  775. vtype:=$ff;
  776. vaddr:=false;
  777. lt:=hp.left.resulttype.def;
  778. case lt.deftype of
  779. enumdef,
  780. orddef :
  781. begin
  782. if is_64bitint(lt) then
  783. begin
  784. case torddef(lt).typ of
  785. s64bit:
  786. vtype:=vtInt64;
  787. u64bit:
  788. vtype:=vtQWord;
  789. end;
  790. if not(nf_cargs in flags) then
  791. begin
  792. freetemp:=false;
  793. vaddr:=true;
  794. end;
  795. end
  796. else if (lt.deftype=enumdef) or
  797. is_integer(lt) then
  798. vtype:=vtInteger
  799. else
  800. if is_boolean(lt) then
  801. vtype:=vtBoolean
  802. else
  803. if (lt.deftype=orddef) then
  804. begin
  805. case torddef(lt).typ of
  806. uchar:
  807. vtype:=vtChar;
  808. uwidechar:
  809. vtype:=vtWideChar;
  810. end;
  811. end;
  812. end;
  813. floatdef :
  814. begin
  815. vtype:=vtExtended;
  816. if not(nf_cargs in flags) then
  817. begin
  818. freetemp:=false;
  819. vaddr:=true;
  820. end;
  821. end;
  822. procvardef,
  823. pointerdef :
  824. begin
  825. if is_pchar(lt) then
  826. vtype:=vtPChar
  827. else
  828. vtype:=vtPointer;
  829. end;
  830. variantdef :
  831. begin
  832. vtype:=vtVariant;
  833. vaddr:=true;
  834. freetemp:=false;
  835. end;
  836. classrefdef :
  837. vtype:=vtClass;
  838. objectdef :
  839. vtype:=vtObject;
  840. stringdef :
  841. begin
  842. if is_shortstring(lt) then
  843. begin
  844. vtype:=vtString;
  845. vaddr:=true;
  846. freetemp:=false;
  847. end
  848. else
  849. if is_ansistring(lt) then
  850. begin
  851. vtype:=vtAnsiString;
  852. freetemp:=false;
  853. end
  854. else
  855. if is_widestring(lt) then
  856. begin
  857. vtype:=vtWideString;
  858. freetemp:=false;
  859. end;
  860. end;
  861. end;
  862. if vtype=$ff then
  863. internalerror(14357);
  864. { write C style pushes or an pascal array }
  865. if nf_cargs in flags then
  866. begin
  867. if vaddr then
  868. begin
  869. location_force_mem(exprasmlist,hp.left.location);
  870. cg.a_paramaddr_ref(exprasmlist,hp.left.location.reference,paralocdummy);
  871. location_release(exprasmlist,hp.left.location);
  872. if freetemp then
  873. location_freetemp(exprasmlist,hp.left.location);
  874. inc(pushedparasize,pointer_size);
  875. end
  876. else
  877. if vtype in [vtInt64,vtQword,vtExtended] then
  878. push_value_para(exprasmlist,hp.left,pocall_cdecl,0,4,paralocdummy)
  879. else
  880. begin
  881. cg.a_param_loc(exprasmlist,hp.left.location,paralocdummy);
  882. inc(pushedparasize,pointer_size);
  883. end;
  884. end
  885. else
  886. begin
  887. { write changing field update href to the next element }
  888. inc(href.offset,4);
  889. if vaddr then
  890. begin
  891. location_force_mem(exprasmlist,hp.left.location);
  892. {$ifdef newra}
  893. tmpreg:=rg.getaddressregister(exprasmlist);
  894. {$else}
  895. tmpreg:=cg.get_scratch_reg_address(exprasmlist);
  896. {$endif}
  897. cg.a_loadaddr_ref_reg(exprasmlist,hp.left.location.reference,tmpreg);
  898. cg.a_load_reg_ref(exprasmlist,OS_ADDR,tmpreg,href);
  899. {$ifdef newra}
  900. rg.ungetregisterint(exprasmlist,tmpreg);
  901. {$else}
  902. cg.free_scratch_reg(exprasmlist,tmpreg);
  903. {$endif}
  904. location_release(exprasmlist,hp.left.location);
  905. if freetemp then
  906. location_freetemp(exprasmlist,hp.left.location);
  907. end
  908. else
  909. begin
  910. location_release(exprasmlist,hp.left.location);
  911. cg.a_load_loc_ref(exprasmlist,hp.left.location,href);
  912. end;
  913. { update href to the vtype field and write it }
  914. dec(href.offset,4);
  915. cg.a_load_const_ref(exprasmlist, OS_INT,vtype,href);
  916. { goto next array element }
  917. inc(href.offset,8);
  918. end;
  919. end
  920. else
  921. { normal array constructor of the same type }
  922. begin
  923. location_release(exprasmlist,hp.left.location);
  924. case hp.left.location.loc of
  925. LOC_FPUREGISTER,
  926. LOC_CFPUREGISTER :
  927. begin
  928. location_release(exprasmlist,hp.left.location);
  929. cg.a_loadfpu_reg_ref(exprasmlist,hp.left.location.size,hp.left.location.register,href);
  930. end;
  931. LOC_REFERENCE,
  932. LOC_CREFERENCE :
  933. begin
  934. cg.g_concatcopy(exprasmlist,hp.left.location.reference,href,elesize,freetemp,false);
  935. end;
  936. else
  937. begin
  938. if hp.left.location.size in [OS_64,OS_S64] then
  939. cg64.a_load64_loc_ref(exprasmlist,hp.left.location,href)
  940. else
  941. cg.a_load_loc_ref(exprasmlist,hp.left.location,href);
  942. end;
  943. end;
  944. inc(href.offset,elesize);
  945. end;
  946. end;
  947. { load next entry }
  948. hp:=tarrayconstructornode(hp.right);
  949. end;
  950. end;
  951. begin
  952. cloadnode:=tcgloadnode;
  953. cassignmentnode:=tcgassignmentnode;
  954. cfuncretnode:=tcgfuncretnode;
  955. carrayconstructornode:=tcgarrayconstructornode;
  956. end.
  957. {
  958. $Log$
  959. Revision 1.49 2003-04-22 23:50:22 peter
  960. * firstpass uses expectloc
  961. * checks if there are differences between the expectloc and
  962. location.loc from secondpass in EXTDEBUG
  963. Revision 1.48 2003/04/22 10:09:35 daniel
  964. + Implemented the actual register allocator
  965. + Scratch registers unavailable when new register allocator used
  966. + maybe_save/maybe_restore unavailable when new register allocator used
  967. Revision 1.47 2003/04/06 21:11:23 olle
  968. * changed newasmsymbol to newasmsymboldata for data symbols
  969. Revision 1.46 2003/03/28 19:16:56 peter
  970. * generic constructor working for i386
  971. * remove fixed self register
  972. * esi added as address register for i386
  973. Revision 1.45 2003/02/19 22:00:14 daniel
  974. * Code generator converted to new register notation
  975. - Horribily outdated todo.txt removed
  976. Revision 1.44 2003/01/08 18:43:56 daniel
  977. * Tregister changed into a record
  978. Revision 1.43 2003/01/05 22:44:14 peter
  979. * remove a lot of code to support typen in loadn-procsym
  980. Revision 1.42 2002/12/20 18:13:46 peter
  981. * fixes for fpu values in arrayconstructor
  982. Revision 1.41 2002/11/27 20:04:39 peter
  983. * cdecl array of const fixes
  984. Revision 1.40 2002/11/25 17:43:18 peter
  985. * splitted defbase in defutil,symutil,defcmp
  986. * merged isconvertable and is_equal into compare_defs(_ext)
  987. * made operator search faster by walking the list only once
  988. Revision 1.39 2002/11/22 16:22:45 jonas
  989. * fixed error in my previous commit (the size of the location of the
  990. funcretnode must be based on the current resulttype of the node and not
  991. the resulttype defined by the function; these can be different in case
  992. of "absolute" declarations)
  993. Revision 1.38 2002/11/18 17:31:54 peter
  994. * pass proccalloption to ret_in_xxx and push_xxx functions
  995. Revision 1.37 2002/11/15 21:16:39 jonas
  996. * proper fix for tw2110, also fixes tb0416 (funcretnode of parent
  997. function was handled wrong inside nested functions/procedures)
  998. Revision 1.36 2002/11/15 01:58:51 peter
  999. * merged changes from 1.0.7 up to 04-11
  1000. - -V option for generating bug report tracing
  1001. - more tracing for option parsing
  1002. - errors for cdecl and high()
  1003. - win32 import stabs
  1004. - win32 records<=8 are returned in eax:edx (turned off by default)
  1005. - heaptrc update
  1006. - more info for temp management in .s file with EXTDEBUG
  1007. Revision 1.35 2002/10/14 19:44:13 peter
  1008. * (hacked) new threadvar relocate code
  1009. Revision 1.34 2002/10/13 11:22:06 florian
  1010. * fixed threadvars
  1011. Revision 1.33 2002/10/03 21:32:02 carl
  1012. * bugfix for 2110 (without -Or), wrong checking was done in returntype
  1013. Revision 1.32 2002/09/30 07:00:46 florian
  1014. * fixes to common code to get the alpha compiler compiled applied
  1015. Revision 1.31 2002/09/26 15:02:05 florian
  1016. + support of passing variants to "array of const"
  1017. Revision 1.30 2002/09/17 18:54:02 jonas
  1018. * a_load_reg_reg() now has two size parameters: source and dest. This
  1019. allows some optimizations on architectures that don't encode the
  1020. register size in the register name.
  1021. Revision 1.29 2002/09/07 15:25:03 peter
  1022. * old logs removed and tabs fixed
  1023. Revision 1.28 2002/09/01 19:26:32 peter
  1024. * fixed register variable loading from parasymtable, the call by
  1025. reference code was moved wrong
  1026. Revision 1.27 2002/09/01 12:15:40 peter
  1027. * fixed loading of procvar of object when the object is initialized
  1028. with 0
  1029. Revision 1.26 2002/08/25 19:25:18 peter
  1030. * sym.insert_in_data removed
  1031. * symtable.insertvardata/insertconstdata added
  1032. * removed insert_in_data call from symtable.insert, it needs to be
  1033. called separatly. This allows to deref the address calculation
  1034. * procedures now calculate the parast addresses after the procedure
  1035. directives are parsed. This fixes the cdecl parast problem
  1036. * push_addr_param has an extra argument that specifies if cdecl is used
  1037. or not
  1038. Revision 1.25 2002/08/23 16:14:48 peter
  1039. * tempgen cleanup
  1040. * tt_noreuse temp type added that will be used in genentrycode
  1041. Revision 1.24 2002/08/17 09:23:35 florian
  1042. * first part of procinfo rewrite
  1043. Revision 1.23 2002/08/14 18:13:28 jonas
  1044. * adapted previous fix to Peter's asmsymbol patch
  1045. Revision 1.22 2002/08/14 18:00:42 jonas
  1046. * fixed tb0403
  1047. Revision 1.21 2002/08/13 21:40:56 florian
  1048. * more fixes for ppc calling conventions
  1049. Revision 1.20 2002/08/11 14:32:26 peter
  1050. * renamed current_library to objectlibrary
  1051. Revision 1.19 2002/08/11 13:24:12 peter
  1052. * saving of asmsymbols in ppu supported
  1053. * asmsymbollist global is removed and moved into a new class
  1054. tasmlibrarydata that will hold the info of a .a file which
  1055. corresponds with a single module. Added librarydata to tmodule
  1056. to keep the library info stored for the module. In the future the
  1057. objectfiles will also be stored to the tasmlibrarydata class
  1058. * all getlabel/newasmsymbol and friends are moved to the new class
  1059. Revision 1.18 2002/08/06 20:55:21 florian
  1060. * first part of ppc calling conventions fix
  1061. Revision 1.17 2002/07/28 09:25:37 carl
  1062. + correct size of parameter (64-bit portability)
  1063. Revision 1.16 2002/07/27 19:53:51 jonas
  1064. + generic implementation of tcg.g_flags2ref()
  1065. * tcg.flags2xxx() now also needs a size parameter
  1066. Revision 1.15 2002/07/20 11:57:54 florian
  1067. * types.pas renamed to defbase.pas because D6 contains a types
  1068. unit so this would conflicts if D6 programms are compiled
  1069. + Willamette/SSE2 instructions to assembler added
  1070. Revision 1.14 2002/07/16 09:17:44 florian
  1071. * threadvar relocation result wasn't handled properly, it could cause
  1072. a crash
  1073. Revision 1.13 2002/07/11 14:41:28 florian
  1074. * start of the new generic parameter handling
  1075. Revision 1.12 2002/07/07 09:52:32 florian
  1076. * powerpc target fixed, very simple units can be compiled
  1077. * some basic stuff for better callparanode handling, far from being finished
  1078. Revision 1.11 2002/07/01 18:46:23 peter
  1079. * internal linker
  1080. * reorganized aasm layer
  1081. Revision 1.10 2002/07/01 16:23:53 peter
  1082. * cg64 patch
  1083. * basics for currency
  1084. * asnode updates for class and interface (not finished)
  1085. Revision 1.9 2002/05/20 13:30:40 carl
  1086. * bugfix of hdisponen (base must be set, not index)
  1087. * more portability fixes
  1088. }