ncgutil.pas 91 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl
  4. Helper routines for all code generators
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit ncgutil;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. node,cpuinfo,
  23. globtype,
  24. cpubase,cpupara,
  25. aasmbase,aasmtai,aasmcpu,
  26. cginfo,symbase,symdef,symtype,
  27. {$ifndef cpu64bit}
  28. cg64f32,
  29. {$endif cpu64bit}
  30. rgobj;
  31. type
  32. tloadregvars = (lr_dont_load_regvars, lr_load_regvars);
  33. tmaybesave = record
  34. saved : boolean;
  35. ref : treference;
  36. end;
  37. procedure firstcomplex(p : tbinarynode);
  38. procedure maketojumpbool(list:TAAsmoutput; p : tnode; loadregvars: tloadregvars);
  39. procedure remove_non_regvars_from_loc(const t: tlocation; var regs:Tsupregset);
  40. procedure location_force_reg(list: TAAsmoutput;var l:tlocation;dst_size:TCGSize;maybeconst:boolean);
  41. procedure location_force_mem(list: TAAsmoutput;var l:tlocation);
  42. {$ifndef newra}
  43. procedure maybe_save(list:taasmoutput;needed:integer;var l:tlocation;var s:tmaybesave);
  44. procedure maybe_restore(list:taasmoutput;var l:tlocation;const s:tmaybesave);
  45. {$endif}
  46. function maybe_pushfpu(list:taasmoutput;needed : byte;var l:tlocation) : boolean;
  47. procedure push_value_para(list:taasmoutput;p:tnode;calloption:tproccalloption;
  48. para_offset:longint;alignment : longint;
  49. const locpara : tparalocation);
  50. procedure genentrycode(list : TAAsmoutput;
  51. make_global:boolean;
  52. stackframe:longint;
  53. var parasize:longint;var nostackframe:boolean;
  54. inlined : boolean);
  55. procedure genexitcode(list : TAAsmoutput;parasize:longint;nostackframe,inlined:boolean);
  56. procedure genimplicitunitinit(list : TAAsmoutput);
  57. procedure genimplicitunitfinal(list : TAAsmoutput);
  58. {#
  59. Allocate the buffers for exception management and setjmp environment.
  60. Return a pointer to these buffers, send them to the utility routine
  61. so they are registered, and then call setjmp.
  62. Then compare the result of setjmp with 0, and if not equal
  63. to zero, then jump to exceptlabel.
  64. Also store the result of setjmp to a temporary space by calling g_save_exception_reason
  65. It is to note that this routine may be called *after* the stackframe of a
  66. routine has been called, therefore on machines where the stack cannot
  67. be modified, all temps should be allocated on the heap instead of the
  68. stack.
  69. }
  70. procedure new_exception(list : taasmoutput;const jmpbuf,envbuf, href : treference;
  71. a : aword; exceptlabel : tasmlabel);
  72. procedure free_exception(list : taasmoutput;const jmpbuf, envbuf, href : treference;
  73. a : aword ; endexceptlabel : tasmlabel; onlyfree : boolean);
  74. implementation
  75. uses
  76. {$ifdef Delphi}
  77. Sysutils,
  78. {$else}
  79. strings,
  80. {$endif}
  81. cutils,cclasses,
  82. globals,systems,verbose,
  83. symconst,symsym,symtable,defutil,
  84. paramgr,fmodule,
  85. cgbase,regvars,
  86. {$ifdef GDB}
  87. gdb,
  88. {$endif GDB}
  89. ncon,
  90. tgobj,cgobj,cgcpu;
  91. const
  92. { Please leave this here, this module should NOT use
  93. exprasmlist, the lists are always passed as arguments.
  94. Declaring it as string here results in an error when compiling (PFV) }
  95. exprasmlist = 'error';
  96. {*****************************************************************************
  97. Misc Helpers
  98. *****************************************************************************}
  99. { DO NOT RELY on the fact that the tnode is not yet swaped
  100. because of inlining code PM }
  101. procedure firstcomplex(p : tbinarynode);
  102. var
  103. hp : tnode;
  104. begin
  105. { always calculate boolean AND and OR from left to right }
  106. if (p.nodetype in [orn,andn]) and
  107. is_boolean(p.left.resulttype.def) then
  108. begin
  109. if nf_swaped in p.flags then
  110. internalerror(234234);
  111. end
  112. else
  113. if (
  114. (p.location.loc=LOC_FPUREGISTER) and
  115. (p.right.registersfpu > p.left.registersfpu)
  116. ) or
  117. (
  118. (
  119. (
  120. ((p.left.registersfpu = 0) and (p.right.registersfpu = 0)) or
  121. (p.location.loc<>LOC_FPUREGISTER)
  122. ) and
  123. (p.left.registers32<p.right.registers32)
  124. ) and
  125. { the following check is appropriate, because all }
  126. { 4 registers are rarely used and it is thereby }
  127. { achieved that the extra code is being dropped }
  128. { by exchanging not commutative operators }
  129. (p.right.registers32<=c_countusableregsint)
  130. ) then
  131. begin
  132. hp:=p.left;
  133. p.left:=p.right;
  134. p.right:=hp;
  135. if nf_swaped in p.flags then
  136. exclude(p.flags,nf_swaped)
  137. else
  138. include(p.flags,nf_swaped);
  139. end;
  140. end;
  141. procedure maketojumpbool(list:TAAsmoutput; p : tnode; loadregvars: tloadregvars);
  142. {
  143. produces jumps to true respectively false labels using boolean expressions
  144. depending on whether the loading of regvars is currently being
  145. synchronized manually (such as in an if-node) or automatically (most of
  146. the other cases where this procedure is called), loadregvars can be
  147. "lr_load_regvars" or "lr_dont_load_regvars"
  148. }
  149. var
  150. opsize : tcgsize;
  151. storepos : tfileposinfo;
  152. begin
  153. if nf_error in p.flags then
  154. exit;
  155. storepos:=aktfilepos;
  156. aktfilepos:=p.fileinfo;
  157. if is_boolean(p.resulttype.def) then
  158. begin
  159. if loadregvars = lr_load_regvars then
  160. load_all_regvars(list);
  161. if is_constboolnode(p) then
  162. begin
  163. if tordconstnode(p).value<>0 then
  164. cg.a_jmp_always(list,truelabel)
  165. else
  166. cg.a_jmp_always(list,falselabel)
  167. end
  168. else
  169. begin
  170. opsize:=def_cgsize(p.resulttype.def);
  171. case p.location.loc of
  172. LOC_CREGISTER,LOC_REGISTER,LOC_CREFERENCE,LOC_REFERENCE :
  173. begin
  174. if (p.location.loc = LOC_CREGISTER) then
  175. load_regvar_reg(list,p.location.register);
  176. cg.a_cmp_const_loc_label(list,opsize,OC_NE,
  177. 0,p.location,truelabel);
  178. { !!! should happen right after cmp (JM) }
  179. location_release(list,p.location);
  180. cg.a_jmp_always(list,falselabel);
  181. end;
  182. {$ifdef cpuflags}
  183. LOC_FLAGS :
  184. begin
  185. cg.a_jmp_flags(list,p.location.resflags,
  186. truelabel);
  187. cg.a_jmp_always(list,falselabel);
  188. end;
  189. {$endif cpuflags}
  190. end;
  191. end;
  192. end
  193. else
  194. internalerror(200112305);
  195. aktfilepos:=storepos;
  196. end;
  197. procedure remove_non_regvars_from_loc(const t: tlocation; var regs:Tsupregset);
  198. begin
  199. case t.loc of
  200. LOC_REGISTER:
  201. begin
  202. { can't be a regvar, since it would be LOC_CREGISTER then }
  203. if t.register.enum<>R_INTREGISTER then
  204. internalerror(200301154);
  205. if t.registerhigh.enum<>R_INTREGISTER then
  206. internalerror(200301154);
  207. exclude(regs,t.register.number shr 8);
  208. if t.registerhigh.enum <> R_NO then
  209. exclude(regs,t.registerhigh.number shr 8);
  210. end;
  211. LOC_CREFERENCE,LOC_REFERENCE:
  212. begin
  213. if t.reference.base.enum<>R_INTREGISTER then
  214. internalerror(200301154);
  215. if t.reference.index.enum<>R_INTREGISTER then
  216. internalerror(200301154);
  217. if not(cs_regalloc in aktglobalswitches) or
  218. ((t.reference.base.number shr 8) in rg.usableregsint) then
  219. exclude(regs,t.reference.base.number shr 8);
  220. if not(cs_regalloc in aktglobalswitches) or
  221. ((t.reference.index.number shr 8) in rg.usableregsint) then
  222. exclude(regs,t.reference.index.number shr 8);
  223. end;
  224. end;
  225. end;
  226. {*****************************************************************************
  227. EXCEPTION MANAGEMENT
  228. *****************************************************************************}
  229. procedure new_exception(list : taasmoutput;const jmpbuf,envbuf, href : treference;
  230. a : aword; exceptlabel : tasmlabel);
  231. var r:Tregister;
  232. begin
  233. cg.a_paramaddr_ref(list,envbuf,paramanager.getintparaloc(3));
  234. cg.a_paramaddr_ref(list,jmpbuf,paramanager.getintparaloc(2));
  235. { push type of exceptionframe }
  236. cg.a_param_const(list,OS_S32,1,paramanager.getintparaloc(1));
  237. cg.a_call_name(list,'FPC_PUSHEXCEPTADDR');
  238. r.enum:=R_INTREGISTER;
  239. r.number:=NR_ACCUMULATOR;
  240. cg.a_param_reg(list,OS_ADDR,r,paramanager.getintparaloc(1));
  241. cg.a_call_name(list,'FPC_SETJMP');
  242. cg.g_exception_reason_save(list, href);
  243. cg.a_cmp_const_reg_label(list,OS_S32,OC_NE,0,r,exceptlabel);
  244. end;
  245. procedure free_exception(list : taasmoutput;const jmpbuf, envbuf, href : treference;
  246. a : aword ; endexceptlabel : tasmlabel; onlyfree : boolean);
  247. var r:Tregister;
  248. begin
  249. cg.a_call_name(list,'FPC_POPADDRSTACK');
  250. if not onlyfree then
  251. begin
  252. cg.g_exception_reason_load(list, href);
  253. r.enum:=R_INTREGISTER;
  254. r.number:=NR_ACCUMULATOR;
  255. cg.a_cmp_const_reg_label(list,OS_S32,OC_EQ,a,r,endexceptlabel);
  256. end;
  257. end;
  258. {*****************************************************************************
  259. TLocation
  260. *****************************************************************************}
  261. {$ifndef cpu64bit}
  262. { 32-bit version }
  263. procedure location_force(list: TAAsmoutput;var l:tlocation;dst_size:TCGSize;maybeconst:boolean);
  264. var
  265. hregister,
  266. hregisterhi : tregister;
  267. hreg64 : tregister64;
  268. hl : tasmlabel;
  269. begin
  270. { handle transformations to 64bit separate }
  271. if dst_size in [OS_64,OS_S64] then
  272. begin
  273. if not (l.size in [OS_64,OS_S64]) then
  274. begin
  275. { load a smaller size to OS_64 }
  276. if l.loc=LOC_REGISTER then
  277. begin
  278. hregister.enum:=R_INTREGISTER;
  279. hregister.number:=(l.registerlow.number and not $ff) or R_SUBWHOLE;
  280. cg.a_load_reg_reg(list,l.size,OS_32,l.registerlow,hregister);
  281. end
  282. else
  283. hregister:=rg.getregisterint(list,OS_INT);
  284. { load value in low register }
  285. case l.loc of
  286. LOC_FLAGS :
  287. cg.g_flags2reg(list,OS_INT,l.resflags,hregister);
  288. LOC_JUMP :
  289. begin
  290. cg.a_label(list,truelabel);
  291. cg.a_load_const_reg(list,OS_INT,1,hregister);
  292. objectlibrary.getlabel(hl);
  293. cg.a_jmp_always(list,hl);
  294. cg.a_label(list,falselabel);
  295. cg.a_load_const_reg(list,OS_INT,0,hregister);
  296. cg.a_label(list,hl);
  297. end;
  298. else
  299. cg.a_load_loc_reg(list,l,hregister);
  300. end;
  301. { reset hi part, take care of the signed bit of the current value }
  302. hregisterhi:=rg.getregisterint(list,OS_INT);
  303. if (dst_size=OS_S64) and
  304. (l.size in [OS_S8,OS_S16,OS_S32]) then
  305. begin
  306. if l.loc=LOC_CONSTANT then
  307. begin
  308. if (longint(l.value)<0) then
  309. cg.a_load_const_reg(list,OS_32,$ffffffff,hregisterhi)
  310. else
  311. cg.a_load_const_reg(list,OS_32,0,hregisterhi);
  312. end
  313. else
  314. begin
  315. cg.a_op_const_reg_reg(list,OP_SAR,OS_32,31,hregister,
  316. hregisterhi);
  317. end;
  318. end
  319. else
  320. cg.a_load_const_reg(list,OS_32,0,hregisterhi);
  321. location_reset(l,LOC_REGISTER,dst_size);
  322. l.registerlow:=hregister;
  323. l.registerhigh:=hregisterhi;
  324. end
  325. else
  326. begin
  327. { 64bit to 64bit }
  328. if (l.loc=LOC_REGISTER) or
  329. ((l.loc=LOC_CREGISTER) and maybeconst) then
  330. begin
  331. hregister:=l.registerlow;
  332. hregisterhi:=l.registerhigh;
  333. end
  334. else
  335. begin
  336. hregister:=rg.getregisterint(list,OS_INT);
  337. hregisterhi:=rg.getregisterint(list,OS_INT);
  338. end;
  339. hreg64.reglo:=hregister;
  340. hreg64.reghi:=hregisterhi;
  341. { load value in new register }
  342. cg64.a_load64_loc_reg(list,l,hreg64);
  343. location_reset(l,LOC_REGISTER,dst_size);
  344. l.registerlow:=hregister;
  345. l.registerhigh:=hregisterhi;
  346. end;
  347. end
  348. else
  349. begin
  350. { transformations to 32bit or smaller }
  351. if l.loc=LOC_REGISTER then
  352. begin
  353. { if the previous was 64bit release the high register }
  354. if l.size in [OS_64,OS_S64] then
  355. begin
  356. rg.ungetregisterint(list,l.registerhigh);
  357. l.registerhigh.enum:=R_NO;
  358. end;
  359. hregister:=l.register;
  360. end
  361. else
  362. begin
  363. { get new register }
  364. if (l.loc=LOC_CREGISTER) and
  365. maybeconst and
  366. (TCGSize2Size[dst_size]=TCGSize2Size[l.size]) then
  367. hregister:=l.register
  368. else
  369. hregister:=rg.getregisterint(list,OS_INT);
  370. end;
  371. if hregister.enum<>R_INTREGISTER then
  372. internalerror(200302022);
  373. hregister.number:=(hregister.number and not $ff) or cgsize2subreg(dst_size);
  374. { load value in new register }
  375. case l.loc of
  376. LOC_FLAGS :
  377. cg.g_flags2reg(list,dst_size,l.resflags,hregister);
  378. LOC_JUMP :
  379. begin
  380. cg.a_label(list,truelabel);
  381. cg.a_load_const_reg(list,dst_size,1,hregister);
  382. objectlibrary.getlabel(hl);
  383. cg.a_jmp_always(list,hl);
  384. cg.a_label(list,falselabel);
  385. cg.a_load_const_reg(list,dst_size,0,hregister);
  386. cg.a_label(list,hl);
  387. end;
  388. else
  389. begin
  390. { load_loc_reg can only handle size >= l.size, when the
  391. new size is smaller then we need to adjust the size
  392. of the orignal and maybe recalculate l.register for i386 }
  393. if (TCGSize2Size[dst_size]<TCGSize2Size[l.size]) then
  394. begin
  395. if (l.loc in [LOC_REGISTER,LOC_CREGISTER]) then
  396. l.register.number:=(l.register.number and not $ff) or cgsize2subreg(dst_size);
  397. { for big endian systems, the reference's offset must }
  398. { be increased in this case, since they have the }
  399. { MSB first in memory and e.g. byte(word_var) should }
  400. { return the second byte in this case (JM) }
  401. if (target_info.endian = ENDIAN_BIG) and
  402. (l.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
  403. inc(l.reference.offset,TCGSize2Size[l.size]-TCGSize2Size[dst_size]);
  404. l.size:=dst_size;
  405. end;
  406. cg.a_load_loc_reg(list,l,hregister);
  407. end;
  408. end;
  409. location_reset(l,LOC_REGISTER,dst_size);
  410. l.register:=hregister;
  411. end;
  412. end;
  413. {$else cpu64bit}
  414. { 64-bit version }
  415. procedure location_force(list: TAAsmoutput;var l:tlocation;dst_size:TCGSize;maybeconst:boolean);
  416. var
  417. hregister : tregister;
  418. hl : tasmlabel;
  419. begin
  420. { handle transformations to 64bit separate }
  421. if dst_size in [OS_64,OS_S64] then
  422. begin
  423. { load a smaller size to OS_64 }
  424. if l.loc=LOC_REGISTER then
  425. hregister:=rg.makeregsize(l.register,OS_INT)
  426. else
  427. hregister:=rg.getregisterint(list,OS_INT);
  428. { load value in low register }
  429. case l.loc of
  430. {$ifdef cpuflags}
  431. LOC_FLAGS :
  432. cg.g_flags2reg(list,OS_INT,l.resflags,hregister);
  433. {$endif cpuflags}
  434. LOC_JUMP :
  435. begin
  436. cg.a_label(list,truelabel);
  437. cg.a_load_const_reg(list,OS_INT,1,hregister);
  438. objectlibrary.getlabel(hl);
  439. cg.a_jmp_always(list,hl);
  440. cg.a_label(list,falselabel);
  441. cg.a_load_const_reg(list,OS_INT,0,hregister);
  442. cg.a_label(list,hl);
  443. end;
  444. else
  445. cg.a_load_loc_reg(list,l,hregister);
  446. end;
  447. location_reset(l,LOC_REGISTER,dst_size);
  448. l.register:=hregister;
  449. end
  450. else
  451. begin
  452. { transformations to 32bit or smaller }
  453. if l.loc=LOC_REGISTER then
  454. begin
  455. hregister:=l.register;
  456. end
  457. else
  458. begin
  459. { get new register }
  460. if (l.loc=LOC_CREGISTER) and
  461. maybeconst and
  462. (TCGSize2Size[dst_size]=TCGSize2Size[l.size]) then
  463. hregister:=l.register
  464. else
  465. hregister:=rg.getregisterint(list,OS_INT);
  466. end;
  467. hregister:=rg.makeregsize(hregister,dst_size);
  468. { load value in new register }
  469. case l.loc of
  470. {$ifdef cpuflags}
  471. LOC_FLAGS :
  472. cg.g_flags2reg(list,dst_size,l.resflags,hregister);
  473. {$endif cpuflags}
  474. LOC_JUMP :
  475. begin
  476. cg.a_label(list,truelabel);
  477. cg.a_load_const_reg(list,dst_size,1,hregister);
  478. objectlibrary.getlabel(hl);
  479. cg.a_jmp_always(list,hl);
  480. cg.a_label(list,falselabel);
  481. cg.a_load_const_reg(list,dst_size,0,hregister);
  482. cg.a_label(list,hl);
  483. end;
  484. else
  485. begin
  486. { load_loc_reg can only handle size >= l.size, when the
  487. new size is smaller then we need to adjust the size
  488. of the orignal and maybe recalculate l.register for i386 }
  489. if (TCGSize2Size[dst_size]<TCGSize2Size[l.size]) then
  490. begin
  491. if (l.loc in [LOC_REGISTER,LOC_CREGISTER]) then
  492. l.register:=rg.makeregsize(l.register,dst_size);
  493. { for big endian systems, the reference's offset must }
  494. { be increased in this case, since they have the }
  495. { MSB first in memory and e.g. byte(word_var) should }
  496. { return the second byte in this case (JM) }
  497. if (target_info.endian = ENDIAN_BIG) and
  498. (l.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
  499. inc(l.reference.offset,TCGSize2Size[l.size]-TCGSize2Size[dst_size]);
  500. l.size:=dst_size;
  501. end;
  502. cg.a_load_loc_reg(list,l,hregister);
  503. end;
  504. end;
  505. location_reset(l,LOC_REGISTER,dst_size);
  506. l.register:=hregister;
  507. end;
  508. end;
  509. {$endif cpu64bit}
  510. procedure location_force_reg(list: TAAsmoutput;var l:tlocation;dst_size:TCGSize;maybeconst:boolean);
  511. begin
  512. { release previous location before demanding a new register }
  513. if (l.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
  514. begin
  515. location_freetemp(list,l);
  516. location_release(list,l);
  517. end;
  518. location_force(list, l, dst_size, maybeconst)
  519. end;
  520. procedure location_force_mem(list: TAAsmoutput;var l:tlocation);
  521. var
  522. r : treference;
  523. begin
  524. case l.loc of
  525. LOC_FPUREGISTER,
  526. LOC_CFPUREGISTER :
  527. begin
  528. tg.GetTemp(list,TCGSize2Size[l.size],tt_normal,r);
  529. cg.a_loadfpu_reg_ref(list,l.size,l.register,r);
  530. location_release(list,l);
  531. location_reset(l,LOC_REFERENCE,l.size);
  532. l.reference:=r;
  533. end;
  534. LOC_CONSTANT,
  535. LOC_REGISTER,
  536. LOC_CREGISTER :
  537. begin
  538. tg.GetTemp(list,TCGSize2Size[l.size],tt_normal,r);
  539. if l.size in [OS_64,OS_S64] then
  540. cg64.a_load64_loc_ref(list,l,r)
  541. else
  542. cg.a_load_loc_ref(list,l,r);
  543. location_release(list,l);
  544. location_reset(l,LOC_REFERENCE,l.size);
  545. l.reference:=r;
  546. end;
  547. LOC_CREFERENCE,
  548. LOC_REFERENCE : ;
  549. else
  550. internalerror(200203219);
  551. end;
  552. end;
  553. {*****************************************************************************
  554. Maybe_Save
  555. *****************************************************************************}
  556. {$ifndef newra}
  557. procedure maybe_save(list:taasmoutput;needed:integer;var l:tlocation;var s:tmaybesave);
  558. begin
  559. s.saved:=false;
  560. if l.loc=LOC_CREGISTER then
  561. begin
  562. s.saved:=true;
  563. exit;
  564. end;
  565. if needed>rg.countunusedregsint then
  566. begin
  567. case l.loc of
  568. LOC_REGISTER :
  569. begin
  570. {$ifndef cpu64bit}
  571. if l.size in [OS_64,OS_S64] then
  572. begin
  573. tg.GetTemp(list,8,tt_normal,s.ref);
  574. cg64.a_load64_reg_ref(list,joinreg64(l.registerlow,l.registerhigh),s.ref);
  575. end
  576. else
  577. {$endif cpu64bit}
  578. begin
  579. tg.GetTemp(list,TCGSize2Size[l.size],tt_normal,s.ref);
  580. cg.a_load_reg_ref(list,l.size,l.register,s.ref);
  581. end;
  582. location_release(list,l);
  583. s.saved:=true;
  584. end;
  585. LOC_REFERENCE,
  586. LOC_CREFERENCE :
  587. begin
  588. if l.reference.base.enum<>R_INTREGISTER then
  589. internalerror(200302101);
  590. if l.reference.index.enum<>R_INTREGISTER then
  591. internalerror(200302101);
  592. if ((l.reference.base.number<>NR_NO) or
  593. (l.reference.index.number<>NR_NO)) then
  594. begin
  595. { load address into a single base register }
  596. if l.reference.index.number<>NR_NO then
  597. begin
  598. cg.a_loadaddr_ref_reg(list,l.reference,l.reference.index);
  599. rg.ungetregisterint(list,l.reference.base);
  600. reference_reset_base(l.reference,l.reference.index,0);
  601. end
  602. else
  603. begin
  604. cg.a_loadaddr_ref_reg(list,l.reference,l.reference.base);
  605. rg.ungetregisterint(list,l.reference.index);
  606. reference_reset_base(l.reference,l.reference.base,0);
  607. end;
  608. { save base register }
  609. tg.GetTemp(list,TCGSize2Size[OS_ADDR],tt_normal,s.ref);
  610. cg.a_load_reg_ref(list,OS_ADDR,l.reference.base,s.ref);
  611. { release }
  612. location_release(list,l);
  613. s.saved:=true;
  614. end;
  615. end;
  616. end;
  617. end;
  618. end;
  619. procedure maybe_restore(list:taasmoutput;var l:tlocation;const s:tmaybesave);
  620. begin
  621. if not s.saved then
  622. exit;
  623. if l.loc=LOC_CREGISTER then
  624. begin
  625. load_regvar_reg(list,l.register);
  626. exit;
  627. end;
  628. case l.loc of
  629. LOC_REGISTER :
  630. begin
  631. {$ifndef cpu64bit}
  632. if l.size in [OS_64,OS_S64] then
  633. begin
  634. l.registerlow:=rg.getregisterint(list,OS_INT);
  635. l.registerhigh:=rg.getregisterint(list,OS_INT);
  636. cg64.a_load64_ref_reg(list,s.ref,joinreg64(l.registerlow,l.registerhigh));
  637. end
  638. else
  639. {$endif cpu64bit}
  640. begin
  641. l.register:=rg.getregisterint(list,OS_INT);
  642. cg.a_load_ref_reg(list,OS_INT,s.ref,l.register);
  643. end;
  644. end;
  645. LOC_CREFERENCE,
  646. LOC_REFERENCE :
  647. begin
  648. reference_reset(l.reference);
  649. l.reference.base:=rg.getaddressregister(list);
  650. cg.a_load_ref_reg(list,OS_ADDR,s.ref,l.reference.base);
  651. end;
  652. end;
  653. tg.ungetiftemp(list,s.ref);
  654. end;
  655. {$endif newra}
  656. function maybe_pushfpu(list:taasmoutput;needed : byte;var l:tlocation) : boolean;
  657. begin
  658. if (needed>=maxfpuregs) and
  659. (l.loc = LOC_FPUREGISTER) then
  660. begin
  661. location_force_mem(list,l);
  662. maybe_pushfpu:=true;
  663. end
  664. else
  665. maybe_pushfpu:=false;
  666. end;
  667. {*****************************************************************************
  668. Push Value Para
  669. *****************************************************************************}
  670. procedure push_value_para(list:taasmoutput;p:tnode;calloption:tproccalloption;
  671. para_offset:longint;alignment : longint;
  672. const locpara : tparalocation);
  673. var
  674. tempreference : treference;
  675. href : treference;
  676. hreg : tregister;
  677. sizetopush,
  678. size : longint;
  679. cgsize : tcgsize;
  680. r:Tregister;
  681. begin
  682. { we've nothing to push when the size of the parameter is 0 }
  683. if p.resulttype.def.size=0 then
  684. exit;
  685. { Move flags and jump in register to make it less complex }
  686. if p.location.loc in [LOC_FLAGS,LOC_JUMP] then
  687. location_force_reg(list,p.location,def_cgsize(p.resulttype.def),false);
  688. { Handle Floating point types differently }
  689. if p.resulttype.def.deftype=floatdef then
  690. begin
  691. case p.location.loc of
  692. LOC_FPUREGISTER,
  693. LOC_CFPUREGISTER:
  694. begin
  695. {$ifdef i386}
  696. size:=align(tfloatdef(p.resulttype.def).size,alignment);
  697. inc(pushedparasize,size);
  698. if calloption<>pocall_inline then
  699. cg.g_stackpointer_alloc(list,size);
  700. {$ifdef GDB}
  701. if (cs_debuginfo in aktmoduleswitches) and
  702. (list.first=list.last) then
  703. list.concat(Tai_force_line.Create);
  704. {$endif GDB}
  705. { this is the easiest case for inlined !! }
  706. r.enum:=stack_pointer_reg;
  707. if calloption=pocall_inline then
  708. reference_reset_base(href,procinfo.framepointer,para_offset-pushedparasize)
  709. else
  710. reference_reset_base(href,r,0);
  711. cg.a_loadfpu_reg_ref(list,
  712. def_cgsize(p.resulttype.def),p.location.register,href);
  713. {$else i386}
  714. cg.a_paramfpu_reg(list,def_cgsize(p.resulttype.def),p.location.register,locpara);
  715. {$endif i386}
  716. end;
  717. LOC_REFERENCE,
  718. LOC_CREFERENCE :
  719. begin
  720. sizetopush:=align(p.resulttype.def.size,alignment);
  721. tempreference:=p.location.reference;
  722. inc(tempreference.offset,sizetopush);
  723. while (sizetopush>0) do
  724. begin
  725. if sizetopush>=4 then
  726. begin
  727. cgsize:=OS_32;
  728. inc(pushedparasize,4);
  729. dec(tempreference.offset,4);
  730. dec(sizetopush,4);
  731. end
  732. else
  733. begin
  734. cgsize:=OS_16;
  735. inc(pushedparasize,2);
  736. dec(tempreference.offset,2);
  737. dec(sizetopush,2);
  738. end;
  739. if calloption=pocall_inline then
  740. begin
  741. reference_reset_base(href,procinfo.framepointer,para_offset-pushedparasize);
  742. cg.a_load_ref_ref(list,cgsize,tempreference,href);
  743. end
  744. else
  745. cg.a_param_ref(list,cgsize,tempreference,locpara);
  746. end;
  747. end;
  748. else
  749. internalerror(200204243);
  750. end;
  751. location_release(list,p.location);
  752. end
  753. else
  754. begin
  755. { copy the value on the stack or use normal parameter push? }
  756. if paramanager.copy_value_on_stack(p.resulttype.def,calloption) then
  757. begin
  758. {$ifdef i386}
  759. if not (p.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
  760. internalerror(200204241);
  761. { push on stack }
  762. size:=align(p.resulttype.def.size,alignment);
  763. inc(pushedparasize,size);
  764. cg.g_stackpointer_alloc(list,size);
  765. r.enum:=R_INTREGISTER;
  766. r.number:=NR_STACK_POINTER_REG;
  767. reference_reset_base(href,r,0);
  768. cg.g_concatcopy(list,p.location.reference,href,size,false,false);
  769. {$else i386}
  770. cg.a_param_copy_ref(list,p.resulttype.def.size,p.location.reference,locpara);
  771. {$endif i386}
  772. end
  773. else
  774. begin
  775. case p.location.loc of
  776. LOC_CONSTANT,
  777. LOC_REGISTER,
  778. LOC_CREGISTER,
  779. LOC_REFERENCE,
  780. LOC_CREFERENCE :
  781. begin
  782. cgsize:=def_cgsize(p.resulttype.def);
  783. if cgsize in [OS_64,OS_S64] then
  784. begin
  785. inc(pushedparasize,8);
  786. if calloption=pocall_inline then
  787. begin
  788. reference_reset_base(href,procinfo.framepointer,para_offset-pushedparasize);
  789. if p.location.loc in [LOC_REFERENCE,LOC_CREFERENCE] then
  790. begin
  791. size:=align(p.resulttype.def.size,alignment);
  792. cg.g_concatcopy(list,p.location.reference,href,size,false,false)
  793. end
  794. else
  795. cg64.a_load64_loc_ref(list,p.location,href);
  796. end
  797. else
  798. cg64.a_param64_loc(list,p.location,locpara);
  799. end
  800. else
  801. begin
  802. case cgsize of
  803. OS_8,OS_S8 :
  804. begin
  805. if alignment=4 then
  806. cgsize:=OS_32
  807. else
  808. cgsize:=OS_16;
  809. end;
  810. OS_16,OS_S16 :
  811. begin
  812. if alignment=4 then
  813. cgsize:=OS_32;
  814. end;
  815. end;
  816. { update register to use to match alignment }
  817. if p.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
  818. begin
  819. if p.location.register.enum<>R_INTREGISTER then
  820. internalerror(200302024);
  821. hreg:=p.location.register;
  822. p.location.register.number:=(p.location.register.number and not $ff) or cgsize2subreg(cgsize);
  823. end;
  824. inc(pushedparasize,alignment);
  825. if calloption=pocall_inline then
  826. begin
  827. reference_reset_base(href,procinfo.framepointer,para_offset-pushedparasize);
  828. if p.location.loc in [LOC_REFERENCE,LOC_CREFERENCE] then
  829. begin
  830. size:=align(p.resulttype.def.size,alignment);
  831. cg.g_concatcopy(list,p.location.reference,href,size,false,false)
  832. end
  833. else
  834. cg.a_load_loc_ref(list,p.location,href);
  835. end
  836. else
  837. cg.a_param_loc(list,p.location,locpara);
  838. { restore old register }
  839. if p.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
  840. p.location.register:=hreg;
  841. end;
  842. location_release(list,p.location);
  843. end;
  844. {$ifdef SUPPORT_MMX}
  845. LOC_MMXREGISTER,
  846. LOC_CMMXREGISTER:
  847. begin
  848. inc(pushedparasize,8);
  849. if calloption=pocall_inline then
  850. begin
  851. reference_reset_base(href,procinfo.framepointer,para_offset-pushedparasize);
  852. cg.a_loadmm_reg_ref(list,p.location.register,href);
  853. end
  854. else
  855. cg.a_parammm_reg(list,p.location.register);
  856. end;
  857. {$endif SUPPORT_MMX}
  858. else
  859. internalerror(200204241);
  860. end;
  861. end;
  862. end;
  863. end;
  864. {****************************************************************************
  865. Entry/Exit Code
  866. ****************************************************************************}
  867. procedure copyvalueparas(p : tnamedindexitem;arg:pointer);
  868. var
  869. href1,href2 : treference;
  870. list : taasmoutput;
  871. begin
  872. list:=taasmoutput(arg);
  873. if (tsym(p).typ=varsym) and
  874. (tvarsym(p).varspez=vs_value) and
  875. (paramanager.push_addr_param(tvarsym(p).vartype.def,procinfo.procdef.proccalloption)) then
  876. begin
  877. reference_reset_base(href1,procinfo.framepointer,tvarsym(p).address+procinfo.para_offset);
  878. if is_open_array(tvarsym(p).vartype.def) or
  879. is_array_of_const(tvarsym(p).vartype.def) then
  880. cg.g_copyvaluepara_openarray(list,href1,tarraydef(tvarsym(p).vartype.def).elesize)
  881. else
  882. begin
  883. reference_reset_base(href2,procinfo.framepointer,-tvarsym(p).localvarsym.address+tvarsym(p).localvarsym.owner.address_fixup);
  884. if is_shortstring(tvarsym(p).vartype.def) then
  885. cg.g_copyshortstring(list,href1,href2,tstringdef(tvarsym(p).vartype.def).len,false,true)
  886. else
  887. cg.g_concatcopy(list,href1,href2,tvarsym(p).vartype.def.size,true,true);
  888. end;
  889. end;
  890. end;
  891. procedure removevalueparas(p : tnamedindexitem;arg:pointer);
  892. var
  893. href1 : treference;
  894. list : taasmoutput;
  895. begin
  896. list:=taasmoutput(arg);
  897. if (tsym(p).typ=varsym) and
  898. (tvarsym(p).varspez=vs_value) and
  899. (is_open_array(tvarsym(p).vartype.def) or
  900. is_array_of_const(tvarsym(p).vartype.def)) and
  901. (paramanager.push_addr_param(tvarsym(p).vartype.def,procinfo.procdef.proccalloption)) then
  902. begin
  903. reference_reset_base(href1,procinfo.framepointer,tvarsym(p).address+procinfo.para_offset);
  904. cg.g_removevaluepara_openarray(list,href1,tarraydef(tvarsym(p).vartype.def).elesize);
  905. end;
  906. end;
  907. { generates the code for initialisation of local data }
  908. procedure initialize_data(p : tnamedindexitem;arg:pointer);
  909. var
  910. href : treference;
  911. list : taasmoutput;
  912. begin
  913. list:=taasmoutput(arg);
  914. if (tsym(p).typ=varsym) and
  915. not(vo_is_local_copy in tvarsym(p).varoptions) and
  916. assigned(tvarsym(p).vartype.def) and
  917. not(is_class(tvarsym(p).vartype.def)) and
  918. tvarsym(p).vartype.def.needs_inittable then
  919. begin
  920. if assigned(procinfo) and
  921. (cs_implicit_exceptions in aktmoduleswitches) then
  922. procinfo.flags:=procinfo.flags or pi_needs_implicit_finally;
  923. if tsym(p).owner.symtabletype in [localsymtable,inlinelocalsymtable] then
  924. reference_reset_base(href,procinfo.framepointer,-tvarsym(p).address+tvarsym(p).owner.address_fixup)
  925. else
  926. reference_reset_symbol(href,objectlibrary.newasmsymboldata(tvarsym(p).mangledname),0);
  927. cg.g_initialize(list,tvarsym(p).vartype.def,href,false);
  928. end;
  929. end;
  930. { generates the code for finalisation of local data }
  931. procedure finalize_data(p : tnamedindexitem;arg:pointer);
  932. var
  933. href : treference;
  934. list : taasmoutput;
  935. begin
  936. list:=taasmoutput(arg);
  937. case tsym(p).typ of
  938. varsym :
  939. begin
  940. if not(vo_is_local_copy in tvarsym(p).varoptions) and
  941. assigned(tvarsym(p).vartype.def) and
  942. not(is_class(tvarsym(p).vartype.def)) and
  943. tvarsym(p).vartype.def.needs_inittable then
  944. begin
  945. if tsym(p).owner.symtabletype in [localsymtable,inlinelocalsymtable] then
  946. reference_reset_base(href,procinfo.framepointer,-tvarsym(p).address+tvarsym(p).owner.address_fixup)
  947. else
  948. reference_reset_symbol(href,objectlibrary.newasmsymboldata(tvarsym(p).mangledname),0);
  949. cg.g_finalize(list,tvarsym(p).vartype.def,href,false);
  950. end;
  951. end;
  952. typedconstsym :
  953. begin
  954. if ttypedconstsym(p).is_writable and
  955. ttypedconstsym(p).typedconsttype.def.needs_inittable then
  956. begin
  957. reference_reset_symbol(href,objectlibrary.newasmsymboldata(ttypedconstsym(p).mangledname),0);
  958. cg.g_finalize(list,ttypedconstsym(p).typedconsttype.def,href,false);
  959. end;
  960. end;
  961. end;
  962. end;
  963. { generates the code for incrementing the reference count of parameters and
  964. initialize out parameters }
  965. procedure init_paras(p : tnamedindexitem;arg:pointer);
  966. var
  967. href : treference;
  968. tmpreg : tregister;
  969. list : taasmoutput;
  970. begin
  971. list:=taasmoutput(arg);
  972. if (tsym(p).typ=varsym) and
  973. not is_class(tvarsym(p).vartype.def) and
  974. tvarsym(p).vartype.def.needs_inittable then
  975. begin
  976. case tvarsym(p).varspez of
  977. vs_value :
  978. begin
  979. if (cs_implicit_exceptions in aktmoduleswitches) then
  980. procinfo.flags:=procinfo.flags or pi_needs_implicit_finally;
  981. if assigned(tvarsym(p).localvarsym) then
  982. reference_reset_base(href,procinfo.framepointer,
  983. -tvarsym(p).localvarsym.address+tvarsym(p).localvarsym.owner.address_fixup)
  984. else
  985. reference_reset_base(href,procinfo.framepointer,tvarsym(p).address+procinfo.para_offset);
  986. cg.g_incrrefcount(list,tvarsym(p).vartype.def,href);
  987. end;
  988. vs_out :
  989. begin
  990. reference_reset_base(href,procinfo.framepointer,tvarsym(p).address+procinfo.para_offset);
  991. {$ifdef newra}
  992. tmpreg:=rg.getaddressregister(list);
  993. {$else}
  994. tmpreg:=cg.get_scratch_reg_address(list);
  995. {$endif}
  996. cg.a_load_ref_reg(list,OS_ADDR,href,tmpreg);
  997. reference_reset_base(href,tmpreg,0);
  998. cg.g_initialize(list,tvarsym(p).vartype.def,href,false);
  999. {$ifdef newra}
  1000. rg.ungetregisterint(list,tmpreg);
  1001. {$else}
  1002. cg.free_scratch_reg(list,tmpreg);
  1003. {$endif newra}
  1004. end;
  1005. end;
  1006. end;
  1007. end;
  1008. { generates the code for decrementing the reference count of parameters }
  1009. procedure final_paras(p : tnamedindexitem;arg:pointer);
  1010. var
  1011. href : treference;
  1012. list : taasmoutput;
  1013. begin
  1014. list:=taasmoutput(arg);
  1015. if (tsym(p).typ=varsym) and
  1016. not is_class(tvarsym(p).vartype.def) and
  1017. tvarsym(p).vartype.def.needs_inittable then
  1018. begin
  1019. if (tvarsym(p).varspez=vs_value) then
  1020. begin
  1021. if assigned(tvarsym(p).localvarsym) then
  1022. reference_reset_base(href,procinfo.framepointer,
  1023. -tvarsym(p).localvarsym.address+tvarsym(p).localvarsym.owner.address_fixup)
  1024. else
  1025. reference_reset_base(href,procinfo.framepointer,tvarsym(p).address+procinfo.para_offset);
  1026. cg.g_decrrefcount(list,tvarsym(p).vartype.def,href);
  1027. end;
  1028. end;
  1029. end;
  1030. { Initialize temp ansi/widestrings,interfaces }
  1031. procedure inittempvariables(list:taasmoutput);
  1032. var
  1033. hp : ptemprecord;
  1034. href : treference;
  1035. begin
  1036. hp:=tg.templist;
  1037. while assigned(hp) do
  1038. begin
  1039. if hp^.temptype in [tt_ansistring,tt_freeansistring,
  1040. tt_widestring,tt_freewidestring,
  1041. tt_interfacecom,tt_freeinterfacecom] then
  1042. begin
  1043. if (cs_implicit_exceptions in aktmoduleswitches) then
  1044. procinfo.flags:=procinfo.flags or pi_needs_implicit_finally;
  1045. reference_reset_base(href,procinfo.framepointer,hp^.pos);
  1046. cg.a_load_const_ref(list,OS_ADDR,0,href);
  1047. end;
  1048. hp:=hp^.next;
  1049. end;
  1050. end;
  1051. procedure finalizetempvariables(list:taasmoutput);
  1052. var
  1053. hp : ptemprecord;
  1054. href : treference;
  1055. begin
  1056. hp:=tg.templist;
  1057. while assigned(hp) do
  1058. begin
  1059. case hp^.temptype of
  1060. tt_ansistring,
  1061. tt_freeansistring :
  1062. begin
  1063. reference_reset_base(href,procinfo.framepointer,hp^.pos);
  1064. cg.a_paramaddr_ref(list,href,paramanager.getintparaloc(1));
  1065. cg.a_call_name(list,'FPC_ANSISTR_DECR_REF');
  1066. end;
  1067. tt_widestring,
  1068. tt_freewidestring :
  1069. begin
  1070. reference_reset_base(href,procinfo.framepointer,hp^.pos);
  1071. cg.a_paramaddr_ref(list,href,paramanager.getintparaloc(2));
  1072. cg.a_call_name(list,'FPC_WIDESTR_DECR_REF');
  1073. end;
  1074. tt_interfacecom :
  1075. begin
  1076. reference_reset_base(href,procinfo.framepointer,hp^.pos);
  1077. cg.a_paramaddr_ref(list,href,paramanager.getintparaloc(2));
  1078. cg.a_call_name(list,'FPC_INTF_DECR_REF');
  1079. end;
  1080. end;
  1081. hp:=hp^.next;
  1082. end;
  1083. end;
  1084. procedure handle_return_value(list:TAAsmoutput; inlined : boolean;var uses_acc,uses_acchi,uses_fpu : boolean);
  1085. var
  1086. href : treference;
  1087. hreg,r,r2 : tregister;
  1088. cgsize : TCGSize;
  1089. begin
  1090. if not is_void(aktprocdef.rettype.def) then
  1091. begin
  1092. if (tfuncretsym(aktprocdef.funcretsym).funcretstate<>vs_assigned) and
  1093. (not inlined) then
  1094. CGMessage(sym_w_function_result_not_set);
  1095. reference_reset_base(href,procinfo.framepointer,procinfo.return_offset);
  1096. cgsize:=def_cgsize(aktprocdef.rettype.def);
  1097. case aktprocdef.rettype.def.deftype of
  1098. orddef,
  1099. enumdef :
  1100. begin
  1101. uses_acc:=true;
  1102. {$WARNING accumulator was replaced by return_result_reg}
  1103. {Here, we return the function result. In most architectures, the value is
  1104. passed into the accumulator, but in a windowed architecure like sparc a
  1105. function returns in a register and the caller receives it in an other one}
  1106. r.enum:=R_INTREGISTER;
  1107. r.number:=NR_RETURN_RESULT_REG;
  1108. cg.a_reg_alloc(list,r);
  1109. {$ifndef cpu64bit}
  1110. if cgsize in [OS_64,OS_S64] then
  1111. begin
  1112. uses_acchi:=true;
  1113. r.enum:=accumulatorhigh;
  1114. cg.a_reg_alloc(list,r);
  1115. r.enum:=R_INTREGISTER;
  1116. r.number:=NR_ACCUMULATOR;
  1117. r2.enum:=R_INTREGISTER;
  1118. r2.number:=NR_ACCUMULATORHIGH;
  1119. cg64.a_load64_ref_reg(list,href,joinreg64(r,r2));
  1120. end
  1121. else
  1122. {$endif cpu64bit}
  1123. begin
  1124. {$WARNING accumulator was replaced by return_result_reg}
  1125. {Here, we return the function result. In most architectures, the value is
  1126. passed into the accumulator, but in a windowed architecure like sparc a
  1127. function returns in a register and the caller receives it in an other one}
  1128. hreg.enum:=R_INTREGISTER;
  1129. hreg.number:=RS_RETURN_RESULT_REG shl 8 or cgsize2subreg(cgsize);
  1130. cg.a_load_ref_reg(list,cgsize,href,hreg);
  1131. end;
  1132. end;
  1133. floatdef :
  1134. begin
  1135. uses_fpu := true;
  1136. {$ifdef cpufpemu}
  1137. if cs_fp_emulation in aktmoduleswitches then
  1138. r.enum := accumulator
  1139. else
  1140. {$endif cpufpemu}
  1141. r.enum:=fpu_result_reg;
  1142. cg.a_loadfpu_ref_reg(list,cgsize,href,r);
  1143. end;
  1144. else
  1145. begin
  1146. if paramanager.ret_in_acc(aktprocdef.rettype.def,aktprocdef.proccalloption) then
  1147. begin
  1148. uses_acc:=true;
  1149. r.enum:=R_INTREGISTER;
  1150. r.number:=NR_RETURN_RESULT_REG;
  1151. cg.a_reg_alloc(list,r);
  1152. {$ifndef cpu64bit}
  1153. { Win32 can return records in EAX:EDX }
  1154. if cgsize in [OS_64,OS_S64] then
  1155. begin
  1156. uses_acchi:=true;
  1157. r.enum:=accumulatorhigh;
  1158. cg.a_reg_alloc(list,r);
  1159. r.enum:=R_INTREGISTER;
  1160. r.number:=NR_ACCUMULATOR;
  1161. r2.enum:=R_INTREGISTER;
  1162. r2.number:=NR_ACCUMULATORHIGH;
  1163. cg64.a_load64_ref_reg(list,href,joinreg64(r,r2));
  1164. end
  1165. else
  1166. {$endif cpu64bit}
  1167. r.enum:=R_INTREGISTER;
  1168. r.number:=NR_ACCUMULATOR;
  1169. cg.a_load_ref_reg(list,cgsize,href,r);
  1170. end
  1171. end;
  1172. end;
  1173. end;
  1174. end;
  1175. procedure handle_fast_exit_return_value(list:TAAsmoutput);
  1176. var
  1177. href : treference;
  1178. hreg : tregister;
  1179. cgsize : TCGSize;
  1180. r,r2 : Tregister;
  1181. begin
  1182. if not is_void(aktprocdef.rettype.def) then
  1183. begin
  1184. reference_reset_base(href,procinfo.framepointer,procinfo.return_offset);
  1185. cgsize:=def_cgsize(aktprocdef.rettype.def);
  1186. case aktprocdef.rettype.def.deftype of
  1187. orddef,
  1188. enumdef :
  1189. begin
  1190. {$ifndef cpu64bit}
  1191. r.enum:=accumulator;
  1192. r2.enum:=accumulatorhigh;
  1193. if cgsize in [OS_64,OS_S64] then
  1194. cg64.a_load64_reg_ref(list,joinreg64(r,r2),href)
  1195. else
  1196. {$endif cpu64bit}
  1197. begin
  1198. hreg:=rg.makeregsize(r,cgsize);
  1199. cg.a_load_reg_ref(list,cgsize,hreg,href);
  1200. end;
  1201. end;
  1202. floatdef :
  1203. begin
  1204. {$ifdef cpufpemu}
  1205. if cs_fp_emulation in aktmoduleswitches then
  1206. r.enum := accumulator
  1207. else
  1208. {$endif cpufpemu}
  1209. r.enum:=fpu_result_reg;
  1210. cg.a_loadfpu_reg_ref(list,cgsize,r,href);
  1211. end;
  1212. else
  1213. begin
  1214. r.enum:=accumulator;
  1215. if paramanager.ret_in_acc(aktprocdef.rettype.def,aktprocdef.proccalloption) then
  1216. cg.a_load_reg_ref(list,cgsize,r,href);
  1217. end;
  1218. end;
  1219. end;
  1220. end;
  1221. procedure genentrycode(list : TAAsmoutput;
  1222. make_global:boolean;
  1223. stackframe:longint;
  1224. var parasize:longint;var nostackframe:boolean;
  1225. inlined : boolean);
  1226. var
  1227. hs : string;
  1228. href : treference;
  1229. stackalloclist : taasmoutput;
  1230. hp : tparaitem;
  1231. paraloc : tparalocation;
  1232. tmpreg : tregister;
  1233. inheriteddesctructorlabel : tasmlabel;
  1234. begin
  1235. if not inlined then
  1236. stackalloclist:=taasmoutput.Create;
  1237. { the actual stack allocation code, symbol entry point and
  1238. gdb stabs information is generated AFTER the rest of this
  1239. code, since temp. allocation might occur before - carl
  1240. }
  1241. { for the save all registers we can simply use a pusha,popa which
  1242. push edi,esi,ebp,esp(ignored),ebx,edx,ecx,eax }
  1243. if (po_saveregisters in aktprocdef.procoptions) then
  1244. cg.g_save_all_registers(list)
  1245. else
  1246. { should we save edi,esi,ebx like C ? }
  1247. if (po_savestdregs in aktprocdef.procoptions) then
  1248. cg.g_save_standard_registers(list,aktprocdef.usedintregisters);
  1249. { the actual profile code can clobber some registers,
  1250. therefore if the context must be saved, do it before
  1251. the actual call to the profile code
  1252. }
  1253. if (cs_profile in aktmoduleswitches) and
  1254. not(po_assembler in aktprocdef.procoptions) and
  1255. not(inlined) then
  1256. begin
  1257. { non-win32 can call mcout even in main }
  1258. if not (target_info.system in [system_i386_win32,system_i386_wdosx]) then
  1259. cg.g_profilecode(list)
  1260. else
  1261. { wdosx, and win32 should not call mcount before monstartup has been called }
  1262. if not (aktprocdef.proctypeoption=potype_proginit) then
  1263. cg.g_profilecode(list);
  1264. end;
  1265. { a constructor needs a help procedure }
  1266. if (aktprocdef.proctypeoption=potype_constructor) then
  1267. begin
  1268. cg.g_call_constructor_helper(list);
  1269. end;
  1270. if not is_void(aktprocdef.rettype.def) then
  1271. begin
  1272. { for now the pointer to the result can't be a register }
  1273. if not(paramanager.ret_in_reg(aktprocdef.rettype.def,aktprocdef.proccalloption)) then
  1274. begin
  1275. {$ifdef powerpc}
  1276. { no stack space is allocated in this case -> can't save the result reg on the stack }
  1277. if not(po_assembler in aktprocdef.procoptions) then
  1278. {$endif powerpc}
  1279. begin
  1280. paraloc:=paramanager.getfuncretparaloc(aktprocdef);
  1281. reference_reset_base(href,procinfo.framepointer,procinfo.return_offset);
  1282. case paraloc.loc of
  1283. LOC_CREGISTER,
  1284. LOC_REGISTER:
  1285. if not(paraloc.size in [OS_64,OS_S64]) then
  1286. cg.a_load_reg_ref(list,paraloc.size,paraloc.register,href)
  1287. else
  1288. cg64.a_load64_reg_ref(list,paraloc.register64,href);
  1289. LOC_CFPUREGISTER,
  1290. LOC_FPUREGISTER:
  1291. cg.a_load_reg_ref(list,paraloc.size,paraloc.register,href);
  1292. LOC_CMMREGISTER,
  1293. LOC_MMREGISTER:
  1294. cg.a_loadmm_reg_ref(list,paraloc.register,href);
  1295. end;
  1296. end;
  1297. end;
  1298. { initialize return value }
  1299. if (aktprocdef.rettype.def.needs_inittable) then
  1300. begin
  1301. {$ifdef powerpc}
  1302. if (po_assembler in aktprocdef.procoptions) then
  1303. internalerror(200304161);
  1304. {$endif powerpc}
  1305. if (cs_implicit_exceptions in aktmoduleswitches) then
  1306. procinfo.flags:=procinfo.flags or pi_needs_implicit_finally;
  1307. reference_reset_base(href,procinfo.framepointer,procinfo.return_offset);
  1308. cg.g_initialize(list,aktprocdef.rettype.def,href,paramanager.ret_in_param(aktprocdef.rettype.def,aktprocdef.proccalloption));
  1309. end;
  1310. end;
  1311. { initialize local data like ansistrings }
  1312. case aktprocdef.proctypeoption of
  1313. potype_unitinit:
  1314. begin
  1315. { using current_module.globalsymtable is hopefully }
  1316. { more robust than symtablestack and symtablestack.next }
  1317. tsymtable(current_module.globalsymtable).foreach_static({$ifndef TP}@{$endif}initialize_data,list);
  1318. tsymtable(current_module.localsymtable).foreach_static({$ifndef TP}@{$endif}initialize_data,list);
  1319. end;
  1320. { units have seperate code for initilization and finalization }
  1321. potype_unitfinalize: ;
  1322. { program init/final is generated in separate procedure }
  1323. potype_proginit: ;
  1324. else
  1325. aktprocdef.localst.foreach_static({$ifndef TP}@{$endif}initialize_data,list);
  1326. end;
  1327. { initialisizes temp. ansi/wide string data }
  1328. inittempvariables(list);
  1329. { generate copies of call by value parameters }
  1330. if not(po_assembler in aktprocdef.procoptions) then
  1331. aktprocdef.parast.foreach_static({$ifndef TP}@{$endif}copyvalueparas,list);
  1332. if assigned(aktprocdef.parast) then
  1333. begin
  1334. aktprocdef.parast.foreach_static({$ifndef TP}@{$endif}init_paras,list);
  1335. if not (po_assembler in aktprocdef.procoptions) then
  1336. begin
  1337. { move register parameters which aren't regable into memory }
  1338. { we do this after init_paras because it saves some code in init_paras if parameters are in register }
  1339. { instead in memory }
  1340. hp:=tparaitem(procinfo.procdef.para.first);
  1341. while assigned(hp) do
  1342. begin
  1343. if Tvarsym(hp.parasym).reg.enum>lastreg then
  1344. internalerror(200301081);
  1345. if (tvarsym(hp.parasym).reg.enum<>R_NO) then
  1346. case hp.paraloc.loc of
  1347. LOC_CREGISTER,
  1348. LOC_REGISTER:
  1349. // if not(hp.paraloc.size in [OS_S64,OS_64]) then
  1350. cg.a_load_reg_reg(list,hp.paraloc.size,OS_32,hp.paraloc.register,tvarsym(hp.parasym).reg);
  1351. // else
  1352. // cg64.a_load64_reg_reg(list,hp.paraloc.register64,tvarsym(hp.parasym).reg);
  1353. LOC_CFPUREGISTER,
  1354. LOC_FPUREGISTER:
  1355. cg.a_loadfpu_reg_reg(list,hp.paraloc.register,tvarsym(hp.parasym).reg);
  1356. end
  1357. else if (hp.paraloc.loc in [LOC_REGISTER,LOC_FPUREGISTER,LOC_MMREGISTER,
  1358. LOC_CREGISTER,LOC_CFPUREGISTER,LOC_CMMREGISTER]) and
  1359. (tvarsym(hp.parasym).reg.enum=R_NO) then
  1360. begin
  1361. reference_reset_base(href,procinfo.framepointer,tvarsym(hp.parasym).address+
  1362. tvarsym(hp.parasym).owner.address_fixup);
  1363. case hp.paraloc.loc of
  1364. LOC_CREGISTER,
  1365. LOC_REGISTER:
  1366. if not(hp.paraloc.size in [OS_S64,OS_64]) then
  1367. cg.a_load_reg_ref(list,hp.paraloc.size,hp.paraloc.register,href)
  1368. else
  1369. cg64.a_load64_reg_ref(list,hp.paraloc.register64,href);
  1370. LOC_FPUREGISTER,
  1371. LOC_CFPUREGISTER:
  1372. cg.a_loadfpu_reg_ref(list,hp.paraloc.size,hp.paraloc.register,href);
  1373. else
  1374. internalerror(2002081302);
  1375. end;
  1376. end;
  1377. hp:=tparaitem(hp.next);
  1378. end;
  1379. end;
  1380. end;
  1381. if (not inlined) then
  1382. begin
  1383. { call startup helpers from main program }
  1384. if (aktprocdef.proctypeoption=potype_proginit) then
  1385. begin
  1386. { initialize profiling for win32 }
  1387. if (target_info.system in [system_i386_win32,system_i386_wdosx]) and
  1388. (cs_profile in aktmoduleswitches) then
  1389. begin
  1390. reference_reset_symbol(href,objectlibrary.newasmsymboldata('etext'),0);
  1391. cg.a_paramaddr_ref(list,href,paraloc);
  1392. reference_reset_symbol(href,objectlibrary.newasmsymboldata('__image_base__'),0);
  1393. cg.a_paramaddr_ref(list,href,paraloc);
  1394. cg.a_call_name(list,'_monstartup');
  1395. end;
  1396. { initialize units }
  1397. cg.a_call_name(list,'FPC_INITIALIZEUNITS');
  1398. end;
  1399. { do we need an exception frame because of ansi/widestrings/interfaces ? }
  1400. if ((procinfo.flags and pi_needs_implicit_finally)<>0) and
  1401. { but it's useless in init/final code of units }
  1402. not(aktprocdef.proctypeoption in [potype_unitfinalize,potype_unitinit]) then
  1403. begin
  1404. include(rg.usedinproc,accumulator);
  1405. tg.GetTemp(list,JMP_BUF_SIZE,tt_noreuse,procinfo.exception_jmp_ref);
  1406. tg.GetTemp(list,12,tt_noreuse,procinfo.exception_env_ref);
  1407. tg.GetTemp(list,sizeof(aword),tt_noreuse,procinfo.exception_result_ref);
  1408. new_exception(list,procinfo.exception_jmp_ref,
  1409. procinfo.exception_env_ref,
  1410. procinfo.exception_result_ref,1,aktexitlabel);
  1411. end;
  1412. {$ifdef GDB}
  1413. if (cs_debuginfo in aktmoduleswitches) then
  1414. list.concat(Tai_force_line.Create);
  1415. {$endif GDB}
  1416. end;
  1417. { maybe call BeforeDestruction for classes }
  1418. if (aktprocdef.proctypeoption=potype_destructor) and
  1419. is_class(aktprocdef._class) then
  1420. begin
  1421. objectlibrary.getlabel(inheriteddesctructorlabel);
  1422. reference_reset_base(href,procinfo.framepointer,procinfo.inheritedflag_offset);
  1423. cg.a_cmp_const_ref_label(list,OS_ADDR,OC_EQ,0,href,inheriteddesctructorlabel);
  1424. reference_reset_base(href,procinfo.framepointer,procinfo.selfpointer_offset);
  1425. {$ifdef newra}
  1426. tmpreg:=rg.getaddressregister(list);
  1427. {$else}
  1428. tmpreg:=cg.get_scratch_reg_address(list);
  1429. {$endif}
  1430. cg.a_load_ref_reg(list,OS_ADDR,href,tmpreg);
  1431. cg.a_param_reg(list,OS_ADDR,tmpreg,paramanager.getintparaloc(1));
  1432. reference_reset_base(href,tmpreg,0);
  1433. cg.a_load_ref_reg(list,OS_ADDR,href,tmpreg);
  1434. reference_reset_base(href,tmpreg,72);
  1435. cg.a_call_ref(list,href);
  1436. {$ifdef newra}
  1437. rg.ungetregisterint(list,tmpreg);
  1438. {$else}
  1439. cg.free_scratch_reg(list,tmpreg);
  1440. {$endif}
  1441. cg.a_label(list,inheriteddesctructorlabel);
  1442. end;
  1443. if inlined then
  1444. load_regvars(list,nil);
  1445. {************************* Stack allocation **************************}
  1446. { and symbol entry point as well as debug information }
  1447. { will be inserted in front of the rest of this list. }
  1448. { Insert alignment and assembler names }
  1449. if not inlined then
  1450. begin
  1451. { Align, gprof uses 16 byte granularity }
  1452. if (cs_profile in aktmoduleswitches) then
  1453. stackalloclist.concat(Tai_align.Create(16))
  1454. else
  1455. stackalloclist.concat(Tai_align.Create(aktalignment.procalign));
  1456. if (cs_profile in aktmoduleswitches) or
  1457. (aktprocdef.owner.symtabletype=globalsymtable) or
  1458. (assigned(procinfo._class) and (procinfo._class.owner.symtabletype=globalsymtable)) then
  1459. make_global:=true;
  1460. if make_global or ((procinfo.flags and pi_is_global) <> 0) then
  1461. aktprocsym.is_global := True;
  1462. {$ifdef GDB}
  1463. if (cs_debuginfo in aktmoduleswitches) then
  1464. begin
  1465. aktprocdef.concatstabto(stackalloclist);
  1466. aktprocsym.isstabwritten:=true;
  1467. end;
  1468. {$endif GDB}
  1469. repeat
  1470. hs:=aktprocdef.aliasnames.getfirst;
  1471. if hs='' then
  1472. break;
  1473. {$ifdef GDB}
  1474. if (cs_debuginfo in aktmoduleswitches) and
  1475. target_info.use_function_relative_addresses then
  1476. stackalloclist.concat(Tai_stab_function_name.Create(strpnew(hs)));
  1477. {$endif GDB}
  1478. if make_global then
  1479. stackalloclist.concat(Tai_symbol.Createname_global(hs,0))
  1480. else
  1481. stackalloclist.concat(Tai_symbol.Createname(hs,0));
  1482. until false;
  1483. stackframe:=stackframe+tg.gettempsize;
  1484. {$ifndef m68k}
  1485. { give a warning if the limit of local variables is reached }
  1486. if stackframe > maxlocalsize then
  1487. Message(cg_w_localsize_too_big);
  1488. {$endif}
  1489. {$ifndef powerpc}
  1490. { at least for the ppc this applies always, so this code isn't usable (FK) }
  1491. { omit stack frame ? }
  1492. if (procinfo.framepointer.number=NR_STACK_POINTER_REG) then
  1493. begin
  1494. CGMessage(cg_d_stackframe_omited);
  1495. nostackframe:=true;
  1496. if (aktprocdef.proctypeoption in [potype_unitinit,potype_proginit,potype_unitfinalize]) then
  1497. parasize:=0
  1498. else
  1499. parasize:=aktprocdef.parast.datasize+procinfo.para_offset-4;
  1500. if stackframe<>0 then
  1501. cg.g_stackpointer_alloc(stackalloclist,stackframe);
  1502. end
  1503. else
  1504. {$endif powerpc}
  1505. begin
  1506. nostackframe:=false;
  1507. if (aktprocdef.proctypeoption in [potype_unitinit,potype_proginit,potype_unitfinalize]) then
  1508. parasize:=0
  1509. else
  1510. parasize:=aktprocdef.parast.datasize+procinfo.para_offset-target_info.first_parm_offset;
  1511. if (po_interrupt in aktprocdef.procoptions) then
  1512. cg.g_interrupt_stackframe_entry(stackalloclist);
  1513. cg.g_stackframe_entry(stackalloclist,stackframe);
  1514. { never call stack checking before the standard system unit
  1515. has not been initialized
  1516. }
  1517. if (cs_check_stack in aktlocalswitches) and (aktprocdef.proctypeoption<>potype_proginit) then
  1518. cg.g_stackcheck(stackalloclist,stackframe);
  1519. end;
  1520. list.insertlist(stackalloclist);
  1521. stackalloclist.free;
  1522. end;
  1523. {************************* End Stack allocation **************************}
  1524. end;
  1525. procedure genexitcode(list : TAAsmoutput;parasize:longint;nostackframe,inlined:boolean);
  1526. var
  1527. {$ifdef GDB}
  1528. stabsendlabel : tasmlabel;
  1529. mangled_length : longint;
  1530. p : pchar;
  1531. st : string[2];
  1532. {$endif GDB}
  1533. inheritedconstructorlabel,
  1534. okexitlabel,
  1535. noreraiselabel,nodestroycall : tasmlabel;
  1536. href : treference;
  1537. usesacc,
  1538. usesacchi,
  1539. usesself,usesfpu : boolean;
  1540. pd : tprocdef;
  1541. tmpreg,r : Tregister;
  1542. begin
  1543. if aktexit2label.is_used and
  1544. ((procinfo.flags and (pi_needs_implicit_finally or pi_uses_exceptions)) <> 0) then
  1545. begin
  1546. cg.a_jmp_always(list,aktexitlabel);
  1547. cg.a_label(list,aktexit2label);
  1548. handle_fast_exit_return_value(list);
  1549. end;
  1550. if aktexitlabel.is_used then
  1551. list.concat(Tai_label.Create(aktexitlabel));
  1552. cleanup_regvars(list);
  1553. { call the destructor help procedure }
  1554. if (aktprocdef.proctypeoption=potype_destructor) and
  1555. assigned(procinfo._class) then
  1556. cg.g_call_destructor_helper(list);
  1557. { finalize temporary data }
  1558. finalizetempvariables(list);
  1559. { finalize local data like ansistrings}
  1560. case aktprocdef.proctypeoption of
  1561. potype_unitfinalize:
  1562. begin
  1563. { using current_module.globalsymtable is hopefully }
  1564. { more robust than symtablestack and symtablestack.next }
  1565. tsymtable(current_module.globalsymtable).foreach_static({$ifndef TP}@{$endif}finalize_data,list);
  1566. tsymtable(current_module.localsymtable).foreach_static({$ifndef TP}@{$endif}finalize_data,list);
  1567. end;
  1568. { units/progs have separate code for initialization and finalization }
  1569. potype_unitinit: ;
  1570. { program init/final is generated in separate procedure }
  1571. potype_proginit: ;
  1572. else
  1573. aktprocdef.localst.foreach_static({$ifndef TP}@{$endif}finalize_data,list);
  1574. end;
  1575. { finalize paras data }
  1576. if assigned(aktprocdef.parast) then
  1577. aktprocdef.parast.foreach_static({$ifndef TP}@{$endif}final_paras,list);
  1578. { do we need to handle exceptions because of ansi/widestrings ? }
  1579. if not inlined and
  1580. ((procinfo.flags and pi_needs_implicit_finally)<>0) and
  1581. { but it's useless in init/final code of units }
  1582. not(aktprocdef.proctypeoption in [potype_unitfinalize,potype_unitinit]) then
  1583. begin
  1584. { the exception helper routines modify all registers }
  1585. aktprocdef.usedintregisters:=all_intregisters;
  1586. aktprocdef.usedotherregisters:=all_registers;
  1587. objectlibrary.getlabel(noreraiselabel);
  1588. free_exception(list,
  1589. procinfo.exception_jmp_ref,
  1590. procinfo.exception_env_ref,
  1591. procinfo.exception_result_ref,0,
  1592. noreraiselabel,false);
  1593. tg.Ungettemp(list,procinfo.exception_jmp_ref);
  1594. tg.Ungettemp(list,procinfo.exception_env_ref);
  1595. tg.Ungettemp(list,procinfo.exception_result_ref);
  1596. if (aktprocdef.proctypeoption=potype_constructor) then
  1597. begin
  1598. if assigned(procinfo._class) then
  1599. begin
  1600. pd:=procinfo._class.searchdestructor;
  1601. if assigned(pd) then
  1602. begin
  1603. objectlibrary.getlabel(nodestroycall);
  1604. reference_reset_base(href,procinfo.framepointer,procinfo.selfpointer_offset);
  1605. cg.a_cmp_const_ref_label(list,OS_ADDR,OC_EQ,0,href,nodestroycall);
  1606. r:=cg.g_load_self(list);
  1607. if is_class(procinfo._class) then
  1608. begin
  1609. cg.a_param_const(list,OS_INT,1,paramanager.getintparaloc(2));
  1610. cg.a_param_reg(list,OS_ADDR,r,paramanager.getintparaloc(1));
  1611. end
  1612. else if is_object(procinfo._class) then
  1613. begin
  1614. cg.a_param_reg(list,OS_ADDR,r,paramanager.getintparaloc(2));
  1615. reference_reset_symbol(href,objectlibrary.newasmsymboldata(procinfo._class.vmt_mangledname),0);
  1616. cg.a_paramaddr_ref(list,href,paramanager.getintparaloc(1));
  1617. end
  1618. else
  1619. Internalerror(200006164);
  1620. if (po_virtualmethod in pd.procoptions) then
  1621. begin
  1622. reference_reset_base(href,r,0);
  1623. cg.a_load_ref_reg(list,OS_ADDR,href,r);
  1624. reference_reset_base(href,r,procinfo._class.vmtmethodoffset(pd.extnumber));
  1625. cg.a_call_ref(list,href);
  1626. end
  1627. else
  1628. cg.a_call_name(list,pd.mangledname);
  1629. rg.ungetregisterint(list,r);
  1630. { not necessary because the result is never assigned in the
  1631. case of an exception (FK) }
  1632. cg.a_label(list,nodestroycall);
  1633. end;
  1634. end
  1635. end
  1636. else
  1637. begin
  1638. { no constructor }
  1639. { must be the return value finalized before reraising the exception? }
  1640. if (not is_void(aktprocdef.rettype.def)) and
  1641. (aktprocdef.rettype.def.needs_inittable) and
  1642. ((aktprocdef.rettype.def.deftype<>objectdef) or
  1643. not is_class(aktprocdef.rettype.def)) then
  1644. begin
  1645. reference_reset_base(href,procinfo.framepointer,procinfo.return_offset);
  1646. cg.g_finalize(list,aktprocdef.rettype.def,href,paramanager.ret_in_param(aktprocdef.rettype.def,aktprocdef.proccalloption));
  1647. end;
  1648. end;
  1649. cg.a_call_name(list,'FPC_RERAISE');
  1650. cg.a_label(list,noreraiselabel);
  1651. end;
  1652. { call __EXIT for main program }
  1653. if (not DLLsource) and
  1654. (not inlined) and
  1655. (aktprocdef.proctypeoption=potype_proginit) then
  1656. begin
  1657. cg.a_call_name(list,'FPC_DO_EXIT');
  1658. end;
  1659. { handle return value, this is not done for assembler routines when
  1660. they didn't reference the result variable }
  1661. usesacc:=false;
  1662. usesacchi:=false;
  1663. usesself:=false;
  1664. if not(po_assembler in aktprocdef.procoptions) or
  1665. (assigned(aktprocdef.funcretsym) and
  1666. (tfuncretsym(aktprocdef.funcretsym).refcount>1)) then
  1667. begin
  1668. if (aktprocdef.proctypeoption=potype_constructor) then
  1669. begin
  1670. objectlibrary.getlabel(inheritedconstructorlabel);
  1671. objectlibrary.getlabel(okexitlabel);
  1672. cg.a_jmp_always(list,okexitlabel);
  1673. { Failure exit }
  1674. cg.a_label(list,faillabel);
  1675. cg.g_call_fail_helper(list);
  1676. cg.a_jmp_always(list,inheritedconstructorlabel);
  1677. { Success exit }
  1678. cg.a_label(list,okexitlabel);
  1679. r.enum:=R_INTREGISTER;
  1680. r.number:=NR_ACCUMULATOR;
  1681. cg.a_reg_alloc(list,r);
  1682. { maybe call AfterConstructor for classes }
  1683. if is_class(aktprocdef._class) then
  1684. begin
  1685. reference_reset_base(href,procinfo.framepointer,procinfo.vmtpointer_offset);
  1686. cg.a_load_ref_reg(list,OS_ADDR,href,r);
  1687. cg.a_cmp_const_reg_label(list,OS_ADDR,OC_EQ,0,r,inheritedconstructorlabel);
  1688. reference_reset_base(href, procinfo.framepointer,procinfo.selfpointer_offset);
  1689. cg.a_load_ref_reg(list,OS_ADDR,href,r);
  1690. cg.a_param_reg(list,OS_ADDR,r,paramanager.getintparaloc(1));
  1691. reference_reset_base(href,r,0);
  1692. {$ifdef newra}
  1693. tmpreg:=rg.getaddressregister(list);
  1694. {$else newra}
  1695. tmpreg:=cg.get_scratch_reg_address(list);
  1696. {$endif}
  1697. cg.a_load_ref_reg(list,OS_ADDR,href,tmpreg);
  1698. reference_reset_base(href,tmpreg,68);
  1699. cg.a_call_ref(list,href);
  1700. {$ifdef newra}
  1701. rg.ungetregisterint(list,tmpreg);
  1702. {$else}
  1703. cg.free_scratch_reg(list,tmpreg);
  1704. {$endif}
  1705. end;
  1706. { return the self pointer }
  1707. cg.a_label(list,inheritedconstructorlabel);
  1708. reference_reset_base(href, procinfo.framepointer,procinfo.selfpointer_offset);
  1709. cg.a_load_ref_reg(list,OS_ADDR,href,r);
  1710. cg.a_reg_dealloc(list,r);
  1711. usesacc:=true;
  1712. end
  1713. else
  1714. handle_return_value(list,inlined,usesacc,usesacchi,usesfpu)
  1715. end;
  1716. if aktexit2label.is_used and not aktexit2label.is_set then
  1717. cg.a_label(list,aktexit2label);
  1718. {$ifdef GDB}
  1719. if ((cs_debuginfo in aktmoduleswitches) and not inlined) then
  1720. begin
  1721. objectlibrary.getlabel(stabsendlabel);
  1722. cg.a_label(list,stabsendlabel);
  1723. end;
  1724. {$endif GDB}
  1725. { remove copies of call by value parameters when there are also
  1726. registers saved on the stack }
  1727. if ((po_saveregisters in aktprocdef.procoptions) or
  1728. (po_savestdregs in aktprocdef.procoptions)) and
  1729. not(po_assembler in aktprocdef.procoptions) then
  1730. aktprocdef.parast.foreach_static({$ifndef TP}@{$endif}removevalueparas,list);
  1731. { for the save all registers we can simply use a pusha,popa which
  1732. push edi,esi,ebp,esp(ignored),ebx,edx,ecx,eax }
  1733. if (po_saveregisters in aktprocdef.procoptions) then
  1734. cg.g_restore_all_registers(list,usesself,usesacc,usesacchi)
  1735. else
  1736. { should we restore edi ? }
  1737. if (po_savestdregs in aktprocdef.procoptions) then
  1738. cg.g_restore_standard_registers(list,aktprocdef.usedintregisters);
  1739. { remove stackframe }
  1740. if not inlined then
  1741. begin
  1742. if (not nostackframe) then
  1743. cg.g_restore_frame_pointer(list)
  1744. else
  1745. if (tg.gettempsize<>0) then
  1746. begin
  1747. r.enum:=stack_pointer_reg;
  1748. cg.a_op_const_reg(list,OP_ADD,tg.gettempsize,r);
  1749. end;
  1750. end;
  1751. { at last, the return is generated }
  1752. if not inlined then
  1753. begin
  1754. if (po_interrupt in aktprocdef.procoptions) then
  1755. cg.g_interrupt_stackframe_exit(list,usesself,usesacc,usesacchi)
  1756. else
  1757. begin
  1758. {$ifndef i386}
  1759. { give a warning if the limit of parameters allowed for
  1760. certain processors is reached.
  1761. }
  1762. if (parasize > maxparasize) then
  1763. Message(cg_w_parasize_too_big);
  1764. {$endif}
  1765. cg.g_return_from_proc(list,parasize);
  1766. end;
  1767. end;
  1768. if not inlined then
  1769. list.concat(Tai_symbol_end.Createname(aktprocdef.mangledname));
  1770. {$ifdef GDB}
  1771. if (cs_debuginfo in aktmoduleswitches) and not inlined then
  1772. begin
  1773. if assigned(procinfo._class) then
  1774. if (not assigned(procinfo.parent) or
  1775. not assigned(procinfo.parent._class)) then
  1776. begin
  1777. if (po_classmethod in aktprocdef.procoptions) or
  1778. ((po_virtualmethod in aktprocdef.procoptions) and
  1779. (potype_constructor=aktprocdef.proctypeoption)) or
  1780. (po_staticmethod in aktprocdef.procoptions) then
  1781. begin
  1782. list.concat(Tai_stabs.Create(strpnew(
  1783. '"pvmt:p'+tstoreddef(pvmttype.def).numberstring+'",'+
  1784. tostr(N_tsym)+',0,0,'+tostr(procinfo.selfpointer_offset))));
  1785. end
  1786. else
  1787. begin
  1788. if not(is_class(procinfo._class)) then
  1789. st:='v'
  1790. else
  1791. st:='p';
  1792. list.concat(Tai_stabs.Create(strpnew(
  1793. '"$t:'+st+procinfo._class.numberstring+'",'+
  1794. tostr(N_tsym)+',0,0,'+tostr(procinfo.selfpointer_offset))));
  1795. end;
  1796. end
  1797. else
  1798. begin
  1799. if not is_class(procinfo._class) then
  1800. st:='*'
  1801. else
  1802. st:='';
  1803. {$warning GDB self}
  1804. {list.concat(Tai_stabs.Create(strpnew(
  1805. '"$t:r'+st+procinfo._class.numberstring+'",'+
  1806. tostr(N_RSYM)+',0,0,'+tostr(stab_regindex[SELF_POINTER_REG]))));}
  1807. end;
  1808. { define calling EBP as pseudo local var PM }
  1809. { this enables test if the function is a local one !! }
  1810. if assigned(procinfo.parent) and (lexlevel>normal_function_level) then
  1811. list.concat(Tai_stabs.Create(strpnew(
  1812. '"parent_ebp:'+tstoreddef(voidpointertype.def).numberstring+'",'+
  1813. tostr(N_LSYM)+',0,0,'+tostr(procinfo.framepointer_offset))));
  1814. if (not is_void(aktprocdef.rettype.def)) then
  1815. begin
  1816. if paramanager.ret_in_param(aktprocdef.rettype.def,aktprocdef.proccalloption) then
  1817. list.concat(Tai_stabs.Create(strpnew(
  1818. '"'+aktprocsym.name+':X*'+tstoreddef(aktprocdef.rettype.def).numberstring+'",'+
  1819. tostr(N_tsym)+',0,0,'+tostr(procinfo.return_offset))))
  1820. else
  1821. list.concat(Tai_stabs.Create(strpnew(
  1822. '"'+aktprocsym.name+':X'+tstoreddef(aktprocdef.rettype.def).numberstring+'",'+
  1823. tostr(N_tsym)+',0,0,'+tostr(procinfo.return_offset))));
  1824. if (m_result in aktmodeswitches) then
  1825. if paramanager.ret_in_param(aktprocdef.rettype.def,aktprocdef.proccalloption) then
  1826. list.concat(Tai_stabs.Create(strpnew(
  1827. '"RESULT:X*'+tstoreddef(aktprocdef.rettype.def).numberstring+'",'+
  1828. tostr(N_tsym)+',0,0,'+tostr(procinfo.return_offset))))
  1829. else
  1830. list.concat(Tai_stabs.Create(strpnew(
  1831. '"RESULT:X'+tstoreddef(aktprocdef.rettype.def).numberstring+'",'+
  1832. tostr(N_tsym)+',0,0,'+tostr(procinfo.return_offset))));
  1833. end;
  1834. mangled_length:=length(aktprocdef.mangledname);
  1835. getmem(p,2*mangled_length+50);
  1836. strpcopy(p,'192,0,0,');
  1837. strpcopy(strend(p),aktprocdef.mangledname);
  1838. if (target_info.use_function_relative_addresses) then
  1839. begin
  1840. strpcopy(strend(p),'-');
  1841. strpcopy(strend(p),aktprocdef.mangledname);
  1842. end;
  1843. list.concat(Tai_stabn.Create(strnew(p)));
  1844. {List.concat(Tai_stabn.Create(strpnew('192,0,0,'
  1845. +aktprocdef.mangledname))));
  1846. p[0]:='2';p[1]:='2';p[2]:='4';
  1847. strpcopy(strend(p),'_end');}
  1848. strpcopy(p,'224,0,0,'+stabsendlabel.name);
  1849. if (target_info.use_function_relative_addresses) then
  1850. begin
  1851. strpcopy(strend(p),'-');
  1852. strpcopy(strend(p),aktprocdef.mangledname);
  1853. end;
  1854. list.concatlist(withdebuglist);
  1855. list.concat(Tai_stabn.Create(strnew(p)));
  1856. { strpnew('224,0,0,'
  1857. +aktprocdef.mangledname+'_end'))));}
  1858. freemem(p,2*mangled_length+50);
  1859. end;
  1860. {$endif GDB}
  1861. if inlined then
  1862. cleanup_regvars(list);
  1863. end;
  1864. procedure genimplicitunitinit(list : TAAsmoutput);
  1865. begin
  1866. {$ifdef GDB}
  1867. if (cs_debuginfo in aktmoduleswitches) and
  1868. target_info.use_function_relative_addresses then
  1869. list.concat(Tai_stab_function_name.Create(strpnew('INIT$$'+current_module.modulename^)));
  1870. {$endif GDB}
  1871. list.concat(Tai_symbol.Createname_global('INIT$$'+current_module.modulename^,0));
  1872. list.concat(Tai_symbol.Createname_global(target_info.cprefix+current_module.modulename^+'_init',0));
  1873. { using current_module.globalsymtable is hopefully }
  1874. { more robust than symtablestack and symtablestack.next }
  1875. if assigned(current_module.globalsymtable) then
  1876. tsymtable(current_module.globalsymtable).foreach_static({$ifdef FPCPROCVAR}@{$endif}finalize_data,list);
  1877. tsymtable(current_module.localsymtable).foreach_static({$ifdef FPCPROCVAR}@{$endif}finalize_data,list);
  1878. cg.g_return_from_proc(list,0);
  1879. end;
  1880. procedure genimplicitunitfinal(list : TAAsmoutput);
  1881. begin
  1882. {$ifdef GDB}
  1883. if (cs_debuginfo in aktmoduleswitches) and
  1884. target_info.use_function_relative_addresses then
  1885. list.concat(Tai_stab_function_name.Create(strpnew('FINALIZE$$'+current_module.modulename^)));
  1886. {$endif GDB}
  1887. list.concat(Tai_symbol.Createname_global('FINALIZE$$'+current_module.modulename^,0));
  1888. list.concat(Tai_symbol.Createname_global(target_info.cprefix+current_module.modulename^+'_finalize',0));
  1889. { using current_module.globalsymtable is hopefully }
  1890. { more robust than symtablestack and symtablestack.next }
  1891. if assigned(current_module.globalsymtable) then
  1892. tsymtable(current_module.globalsymtable).foreach_static({$ifdef FPCPROCVAR}@{$endif}finalize_data,list);
  1893. tsymtable(current_module.localsymtable).foreach_static({$ifdef FPCPROCVAR}@{$endif}finalize_data,list);
  1894. cg.g_return_from_proc(list,0);
  1895. end;
  1896. end.
  1897. {
  1898. $Log$
  1899. Revision 1.85 2003-04-22 10:09:35 daniel
  1900. + Implemented the actual register allocator
  1901. + Scratch registers unavailable when new register allocator used
  1902. + maybe_save/maybe_restore unavailable when new register allocator used
  1903. Revision 1.84 2003/04/16 09:26:55 jonas
  1904. * assembler procedures now again get a stackframe if they have local
  1905. variables. No space is reserved for a function result however.
  1906. Also, the register parameters aren't automatically saved on the stack
  1907. anymore in assembler procedures.
  1908. Revision 1.83 2003/04/06 21:11:23 olle
  1909. * changed newasmsymbol to newasmsymboldata for data symbols
  1910. Revision 1.82 2003/03/30 20:59:07 peter
  1911. * fix classmethod from classmethod call
  1912. * move BeforeDestruction/AfterConstruction calls to
  1913. genentrycode/genexitcode instead of generating them on the fly
  1914. after a call to a constructor
  1915. Revision 1.81 2003/03/28 19:16:56 peter
  1916. * generic constructor working for i386
  1917. * remove fixed self register
  1918. * esi added as address register for i386
  1919. Revision 1.80 2003/03/17 15:52:20 peter
  1920. * fix range error
  1921. Revision 1.79 2003/03/11 21:46:24 jonas
  1922. * lots of new regallocator fixes, both in generic and ppc-specific code
  1923. (ppc compiler still can't compile the linux system unit though)
  1924. Revision 1.78 2003/02/26 21:15:43 daniel
  1925. * Fixed the optimizer
  1926. Revision 1.77 2003/02/19 22:00:14 daniel
  1927. * Code generator converted to new register notation
  1928. - Horribily outdated todo.txt removed
  1929. Revision 1.76 2003/02/15 22:17:38 carl
  1930. * bugfix of FPU emulation code
  1931. Revision 1.75 2003/01/09 22:00:53 florian
  1932. * fixed some PowerPC issues
  1933. Revision 1.74 2003/01/09 20:41:10 florian
  1934. * fixed broken PowerPC compiler
  1935. Revision 1.73 2003/01/08 18:43:56 daniel
  1936. * Tregister changed into a record
  1937. Revision 1.72 2002/12/29 23:51:43 florian
  1938. * web bug 2214 fixed: ie 10 in const array constructors
  1939. Revision 1.71 2002/12/24 15:56:50 peter
  1940. * stackpointer_alloc added for adjusting ESP. Win32 needs
  1941. this for the pageprotection
  1942. Revision 1.70 2002/12/05 14:39:21 florian
  1943. * added missing then, Carl did you really a make fullcycle :) ?
  1944. Revision 1.69 2002/12/03 22:13:39 carl
  1945. * bugfix of problems with profile code which clobbers some registers
  1946. Revision 1.68 2002/12/01 22:06:59 carl
  1947. * warning of portabilitiy problems with parasize / localsize
  1948. Revision 1.67 2002/11/30 18:44:57 carl
  1949. + profiling support for Win32
  1950. Revision 1.66 2002/11/30 14:39:15 carl
  1951. * try to fix profiling for win32
  1952. Revision 1.65 2002/11/28 23:28:14 florian
  1953. * push_value_para didn't release floatdef locations, fixes tw2045
  1954. Revision 1.64 2002/11/27 02:33:19 peter
  1955. * copy_value_on_stack method added for cdecl record passing
  1956. Revision 1.63 2002/11/25 17:43:18 peter
  1957. * splitted defbase in defutil,symutil,defcmp
  1958. * merged isconvertable and is_equal into compare_defs(_ext)
  1959. * made operator search faster by walking the list only once
  1960. Revision 1.62 2002/11/18 17:31:55 peter
  1961. * pass proccalloption to ret_in_xxx and push_xxx functions
  1962. Revision 1.61 2002/11/17 17:49:08 mazen
  1963. + return_result_reg and function_result_reg are now used, in all plateforms, to pass functions result between called function and its caller. See the explanation of each one
  1964. Revision 1.60 2002/11/17 16:31:56 carl
  1965. * memory optimization (3-4%) : cleanup of tai fields,
  1966. cleanup of tdef and tsym fields.
  1967. * make it work for m68k
  1968. Revision 1.59 2002/11/15 01:58:51 peter
  1969. * merged changes from 1.0.7 up to 04-11
  1970. - -V option for generating bug report tracing
  1971. - more tracing for option parsing
  1972. - errors for cdecl and high()
  1973. - win32 import stabs
  1974. - win32 records<=8 are returned in eax:edx (turned off by default)
  1975. - heaptrc update
  1976. - more info for temp management in .s file with EXTDEBUG
  1977. Revision 1.58 2002/11/10 19:07:45 mazen
  1978. * SPARC calling mechanism almost OK (as in GCC./mppcsparc )
  1979. Revision 1.57 2002/11/03 20:22:40 mazen
  1980. * parameter handling updated
  1981. Revision 1.56 2002/10/16 19:01:43 peter
  1982. + $IMPLICITEXCEPTIONS switch to turn on/off generation of the
  1983. implicit exception frames for procedures with initialized variables
  1984. and for constructors. The default is on for compatibility
  1985. Revision 1.55 2002/10/14 19:42:33 peter
  1986. * only use init tables for threadvars
  1987. Revision 1.54 2002/10/06 19:41:30 peter
  1988. * Add finalization of typed consts
  1989. * Finalization of globals in the main program
  1990. Revision 1.53 2002/10/05 15:18:42 carl
  1991. * fix heap leaks
  1992. Revision 1.52 2002/09/30 07:00:46 florian
  1993. * fixes to common code to get the alpha compiler compiled applied
  1994. Revision 1.51 2002/09/22 14:02:35 carl
  1995. * stack checking cannot be called before system unit is initialized
  1996. * MC68020 define
  1997. Revision 1.50 2002/09/17 18:54:03 jonas
  1998. * a_load_reg_reg() now has two size parameters: source and dest. This
  1999. allows some optimizations on architectures that don't encode the
  2000. register size in the register name.
  2001. Revision 1.49 2002/09/10 21:48:30 florian
  2002. * improved handling of procedures with register calling conventions
  2003. Revision 1.48 2002/09/07 15:25:03 peter
  2004. * old logs removed and tabs fixed
  2005. Revision 1.47 2002/09/02 18:44:48 peter
  2006. * fixed (not) pushing of empty parameters
  2007. * fixed implicit initialization/finalization generation
  2008. * fixed/optimized local copy of value arguments init/final
  2009. Revision 1.46 2002/09/01 19:27:34 peter
  2010. * use index register when available for generating a reference with
  2011. only a signle register. Using the base register could possibly
  2012. destroy the framepointer
  2013. Revision 1.45 2002/09/01 18:50:20 peter
  2014. * fixed maybe_save that did not support a reference with only
  2015. a index register. It now also updates the location with the new
  2016. base register only
  2017. Revision 1.44 2002/09/01 14:42:41 peter
  2018. * removevaluepara added to fix the stackpointer so restoring of
  2019. saved registers works
  2020. Revision 1.43 2002/08/25 19:25:18 peter
  2021. * sym.insert_in_data removed
  2022. * symtable.insertvardata/insertconstdata added
  2023. * removed insert_in_data call from symtable.insert, it needs to be
  2024. called separatly. This allows to deref the address calculation
  2025. * procedures now calculate the parast addresses after the procedure
  2026. directives are parsed. This fixes the cdecl parast problem
  2027. * push_addr_param has an extra argument that specifies if cdecl is used
  2028. or not
  2029. Revision 1.42 2002/08/24 18:38:26 peter
  2030. * really use tt_noreuse for exception frame buffers
  2031. Revision 1.41 2002/08/23 16:14:49 peter
  2032. * tempgen cleanup
  2033. * tt_noreuse temp type added that will be used in genentrycode
  2034. Revision 1.40 2002/08/18 10:42:37 florian
  2035. * remaining assembler writer bugs fixed, the errors in the
  2036. system unit are inline assembler problems
  2037. Revision 1.39 2002/08/17 09:23:36 florian
  2038. * first part of procinfo rewrite
  2039. Revision 1.38 2002/08/16 14:24:57 carl
  2040. * issameref() to test if two references are the same (then emit no opcodes)
  2041. + ret_in_reg to replace ret_in_acc
  2042. (fix some register allocation bugs at the same time)
  2043. + save_std_register now has an extra parameter which is the
  2044. usedinproc registers
  2045. Revision 1.37 2002/08/15 15:15:55 carl
  2046. * jmpbuf size allocation for exceptions is now cpu specific (as it should)
  2047. * more generic nodes for maths
  2048. * several fixes for better m68k support
  2049. Revision 1.36 2002/08/14 19:25:09 carl
  2050. * fix Florian's last commit for m68k compilation
  2051. Revision 1.35 2002/08/13 21:40:56 florian
  2052. * more fixes for ppc calling conventions
  2053. Revision 1.34 2002/08/12 15:08:39 carl
  2054. + stab register indexes for powerpc (moved from gdb to cpubase)
  2055. + tprocessor enumeration moved to cpuinfo
  2056. + linker in target_info is now a class
  2057. * many many updates for m68k (will soon start to compile)
  2058. - removed some ifdef or correct them for correct cpu
  2059. Revision 1.33 2002/08/11 14:32:27 peter
  2060. * renamed current_library to objectlibrary
  2061. Revision 1.32 2002/08/11 13:24:12 peter
  2062. * saving of asmsymbols in ppu supported
  2063. * asmsymbollist global is removed and moved into a new class
  2064. tasmlibrarydata that will hold the info of a .a file which
  2065. corresponds with a single module. Added librarydata to tmodule
  2066. to keep the library info stored for the module. In the future the
  2067. objectfiles will also be stored to the tasmlibrarydata class
  2068. * all getlabel/newasmsymbol and friends are moved to the new class
  2069. Revision 1.31 2002/08/09 19:16:57 carl
  2070. * stack allocation is now done separately (at the end) of genentrycode
  2071. so temps. can be allocated before.
  2072. * fix generic exception handling
  2073. Revision 1.30 2002/08/06 20:55:21 florian
  2074. * first part of ppc calling conventions fix
  2075. Revision 1.29 2002/08/04 19:09:22 carl
  2076. + added generic exception support (still does not work!)
  2077. + more documentation
  2078. Revision 1.28 2002/07/29 21:23:42 florian
  2079. * more fixes for the ppc
  2080. + wrappers for the tcnvnode.first_* stuff introduced
  2081. }