ncgld.pas 50 KB

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