cg386cal.pas 68 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635
  1. {
  2. $Id$
  3. Copyright (c) 1993-98 by Florian Klaempfl
  4. Generate i386 assembler for in call nodes
  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 cg386cal;
  19. interface
  20. { $define AnsiStrRef}
  21. uses
  22. symtable,tree;
  23. procedure secondcallparan(var p : ptree;defcoll : pdefcoll;
  24. push_from_left_to_right,inlined,dword_align : boolean;para_offset : longint);
  25. procedure secondcalln(var p : ptree);
  26. procedure secondprocinline(var p : ptree);
  27. implementation
  28. uses
  29. globtype,systems,
  30. cobjects,verbose,globals,
  31. symconst,aasm,types,
  32. {$ifdef GDB}
  33. gdb,
  34. {$endif GDB}
  35. hcodegen,temp_gen,pass_2,
  36. cpubase,cpuasm,
  37. cgai386,tgeni386,cg386ld;
  38. {*****************************************************************************
  39. SecondCallParaN
  40. *****************************************************************************}
  41. procedure secondcallparan(var p : ptree;defcoll : pdefcoll;
  42. push_from_left_to_right,inlined,dword_align : boolean;para_offset : longint);
  43. procedure maybe_push_high;
  44. begin
  45. { open array ? }
  46. { defcoll^.data can be nil for read/write }
  47. if assigned(defcoll^.data) and
  48. push_high_param(defcoll^.data) then
  49. begin
  50. if assigned(p^.hightree) then
  51. begin
  52. secondpass(p^.hightree);
  53. { this is a longint anyway ! }
  54. push_value_para(p^.hightree,inlined,para_offset,4);
  55. end
  56. else
  57. internalerror(432645);
  58. end;
  59. end;
  60. var
  61. otlabel,oflabel : pasmlabel;
  62. align : longint;
  63. { temporary variables: }
  64. tempdeftype : tdeftype;
  65. r : preference;
  66. begin
  67. { push from left to right if specified }
  68. if push_from_left_to_right and assigned(p^.right) then
  69. secondcallparan(p^.right,defcoll^.next,push_from_left_to_right,
  70. inlined,dword_align,para_offset);
  71. otlabel:=truelabel;
  72. oflabel:=falselabel;
  73. getlabel(truelabel);
  74. getlabel(falselabel);
  75. secondpass(p^.left);
  76. { filter array constructor with c styled args }
  77. if is_array_constructor(p^.left^.resulttype) and p^.left^.cargs then
  78. begin
  79. { nothing, everything is already pushed }
  80. end
  81. { in codegen.handleread.. defcoll^.data is set to nil }
  82. else if assigned(defcoll^.data) and
  83. (defcoll^.data^.deftype=formaldef) then
  84. begin
  85. { allow @var }
  86. inc(pushedparasize,4);
  87. if p^.left^.treetype=addrn then
  88. begin
  89. { always a register }
  90. if inlined then
  91. begin
  92. r:=new_reference(procinfo.framepointer,para_offset-pushedparasize);
  93. emit_reg_ref(A_MOV,S_L,
  94. p^.left^.location.register,r);
  95. end
  96. else
  97. emit_reg(A_PUSH,S_L,p^.left^.location.register);
  98. ungetregister32(p^.left^.location.register);
  99. end
  100. else
  101. begin
  102. if not(p^.left^.location.loc in [LOC_MEM,LOC_REFERENCE]) then
  103. CGMessage(type_e_mismatch)
  104. else
  105. begin
  106. if inlined then
  107. begin
  108. emit_ref_reg(A_LEA,S_L,
  109. newreference(p^.left^.location.reference),R_EDI);
  110. r:=new_reference(procinfo.framepointer,para_offset-pushedparasize);
  111. emit_reg_ref(A_MOV,S_L,R_EDI,r);
  112. end
  113. else
  114. emitpushreferenceaddr(p^.left^.location.reference);
  115. del_reference(p^.left^.location.reference);
  116. end;
  117. end;
  118. end
  119. { handle call by reference parameter }
  120. else if (defcoll^.paratyp=vs_var) then
  121. begin
  122. if (p^.left^.location.loc<>LOC_REFERENCE) then
  123. CGMessage(cg_e_var_must_be_reference);
  124. maybe_push_high;
  125. inc(pushedparasize,4);
  126. if inlined then
  127. begin
  128. emit_ref_reg(A_LEA,S_L,
  129. newreference(p^.left^.location.reference),R_EDI);
  130. r:=new_reference(procinfo.framepointer,para_offset-pushedparasize);
  131. emit_reg_ref(A_MOV,S_L,R_EDI,r);
  132. end
  133. else
  134. emitpushreferenceaddr(p^.left^.location.reference);
  135. del_reference(p^.left^.location.reference);
  136. end
  137. else
  138. begin
  139. tempdeftype:=p^.resulttype^.deftype;
  140. if tempdeftype=filedef then
  141. CGMessage(cg_e_file_must_call_by_reference);
  142. if push_addr_param(p^.resulttype) then
  143. begin
  144. maybe_push_high;
  145. inc(pushedparasize,4);
  146. if inlined then
  147. begin
  148. emit_ref_reg(A_LEA,S_L,
  149. newreference(p^.left^.location.reference),R_EDI);
  150. r:=new_reference(procinfo.framepointer,para_offset-pushedparasize);
  151. emit_reg_ref(A_MOV,S_L,
  152. R_EDI,r);
  153. end
  154. else
  155. emitpushreferenceaddr(p^.left^.location.reference);
  156. del_reference(p^.left^.location.reference);
  157. end
  158. else
  159. begin
  160. align:=target_os.stackalignment;
  161. if dword_align then
  162. align:=4;
  163. push_value_para(p^.left,inlined,para_offset,align);
  164. end;
  165. end;
  166. freelabel(truelabel);
  167. freelabel(falselabel);
  168. truelabel:=otlabel;
  169. falselabel:=oflabel;
  170. { push from right to left }
  171. if not push_from_left_to_right and assigned(p^.right) then
  172. secondcallparan(p^.right,defcoll^.next,push_from_left_to_right,
  173. inlined,dword_align,para_offset);
  174. end;
  175. {*****************************************************************************
  176. SecondCallN
  177. *****************************************************************************}
  178. procedure secondcalln(var p : ptree);
  179. var
  180. unusedregisters : tregisterset;
  181. pushed : tpushed;
  182. hr,funcretref : treference;
  183. hregister,hregister2 : tregister;
  184. oldpushedparasize : longint;
  185. { true if ESI must be loaded again after the subroutine }
  186. loadesi : boolean;
  187. { true if a virtual method must be called directly }
  188. no_virtual_call : boolean;
  189. { true if we produce a con- or destrutor in a call }
  190. is_con_or_destructor : boolean;
  191. { true if a constructor is called again }
  192. extended_new : boolean;
  193. { adress returned from an I/O-error }
  194. iolabel : pasmlabel;
  195. { lexlevel count }
  196. i : longint;
  197. { help reference pointer }
  198. r : preference;
  199. hp,
  200. pp,params : ptree;
  201. inlined : boolean;
  202. inlinecode : ptree;
  203. para_offset : longint;
  204. { instruction for alignement correction }
  205. { corr : pai386;}
  206. { we must pop this size also after !! }
  207. { must_pop : boolean; }
  208. pop_size : longint;
  209. pop_allowed : boolean;
  210. label
  211. dont_call;
  212. begin
  213. reset_reference(p^.location.reference);
  214. extended_new:=false;
  215. iolabel:=nil;
  216. inlinecode:=nil;
  217. inlined:=false;
  218. loadesi:=true;
  219. no_virtual_call:=false;
  220. unusedregisters:=unused;
  221. if not assigned(p^.procdefinition) then
  222. exit;
  223. if (pocall_inline in p^.procdefinition^.proccalloptions) then
  224. begin
  225. inlined:=true;
  226. inlinecode:=p^.right;
  227. { set it to the same lexical level as the local symtable, becuase
  228. the para's are stored there }
  229. pprocdef(p^.procdefinition)^.parast^.symtablelevel:=aktprocsym^.definition^.localst^.symtablelevel;
  230. if assigned(p^.left) then
  231. inlinecode^.para_offset:=gettempofsizepersistant(inlinecode^.para_size);
  232. pprocdef(p^.procdefinition)^.parast^.address_fixup:=inlinecode^.para_offset;
  233. {$ifdef extdebug}
  234. Comment(V_debug,
  235. 'inlined parasymtable is at offset '
  236. +tostr(pprocdef(p^.procdefinition)^.parast^.address_fixup));
  237. exprasmlist^.concat(new(pai_asm_comment,init(
  238. strpnew('inlined parasymtable is at offset '
  239. +tostr(pprocdef(p^.procdefinition)^.parast^.address_fixup)))));
  240. {$endif extdebug}
  241. p^.right:=nil;
  242. { disable further inlining of the same proc
  243. in the args }
  244. {$ifdef INCLUDEOK}
  245. exclude(p^.procdefinition^.proccalloptions,pocall_inline);
  246. {$else}
  247. p^.procdefinition^.proccalloptions:=p^.procdefinition^.proccalloptions-[pocall_inline];
  248. {$endif}
  249. end;
  250. { only if no proc var }
  251. if not(assigned(p^.right)) then
  252. is_con_or_destructor:=(p^.procdefinition^.proctypeoption in [potype_constructor,potype_destructor]);
  253. { proc variables destroy all registers }
  254. if (p^.right=nil) and
  255. { virtual methods too }
  256. not(po_virtualmethod in p^.procdefinition^.procoptions) then
  257. begin
  258. if (cs_check_io in aktlocalswitches) and
  259. (po_iocheck in p^.procdefinition^.procoptions) and
  260. not(po_iocheck in aktprocsym^.definition^.procoptions) then
  261. begin
  262. getlabel(iolabel);
  263. emitlab(iolabel);
  264. end
  265. else
  266. iolabel:=nil;
  267. { save all used registers }
  268. pushusedregisters(pushed,pprocdef(p^.procdefinition)^.usedregisters);
  269. { give used registers through }
  270. usedinproc:=usedinproc or pprocdef(p^.procdefinition)^.usedregisters;
  271. end
  272. else
  273. begin
  274. pushusedregisters(pushed,$ff);
  275. usedinproc:=$ff;
  276. { no IO check for methods and procedure variables }
  277. iolabel:=nil;
  278. end;
  279. { generate the code for the parameter and push them }
  280. oldpushedparasize:=pushedparasize;
  281. pushedparasize:=0;
  282. pop_size:=0;
  283. { no inc esp for inlined procedure
  284. and for objects constructors PM }
  285. if inlined or
  286. ((p^.right=nil) and
  287. (p^.procdefinition^.proctypeoption=potype_constructor) and
  288. { quick'n'dirty check if it is a class or an object }
  289. (p^.resulttype^.deftype=orddef)) then
  290. pop_allowed:=false
  291. else
  292. pop_allowed:=true;
  293. if pop_allowed then
  294. begin
  295. { Old pushedsize aligned on 4 ? }
  296. i:=oldpushedparasize and 3;
  297. if i>0 then
  298. inc(pop_size,4-i);
  299. { This parasize aligned on 4 ? }
  300. i:=p^.procdefinition^.para_size and 3;
  301. if i>0 then
  302. inc(pop_size,4-i);
  303. { insert the opcode and update pushedparasize }
  304. { never push 4 or more !! }
  305. pop_size:=pop_size mod 4;
  306. if pop_size>0 then
  307. begin
  308. inc(pushedparasize,pop_size);
  309. emit_const_reg(A_SUB,S_L,pop_size,R_ESP);
  310. {$ifdef GDB}
  311. if (cs_debuginfo in aktmoduleswitches) and
  312. (exprasmlist^.first=exprasmlist^.last) then
  313. exprasmlist^.concat(new(pai_force_line,init));
  314. {$endif GDB}
  315. end;
  316. end;
  317. if (p^.resulttype<>pdef(voiddef)) and
  318. ret_in_param(p^.resulttype) then
  319. begin
  320. funcretref.symbol:=nil;
  321. {$ifdef test_dest_loc}
  322. if dest_loc_known and (dest_loc_tree=p) and
  323. (dest_loc.loc in [LOC_REFERENCE,LOC_MEM]) then
  324. begin
  325. funcretref:=dest_loc.reference;
  326. if assigned(dest_loc.reference.symbol) then
  327. funcretref.symbol:=stringdup(dest_loc.reference.symbol^);
  328. in_dest_loc:=true;
  329. end
  330. else
  331. {$endif test_dest_loc}
  332. if inlined then
  333. begin
  334. reset_reference(funcretref);
  335. funcretref.offset:=gettempofsizepersistant(p^.procdefinition^.retdef^.size);
  336. funcretref.base:=procinfo.framepointer;
  337. end
  338. else
  339. gettempofsizereference(p^.procdefinition^.retdef^.size,funcretref);
  340. end;
  341. if assigned(p^.left) then
  342. begin
  343. { be found elsewhere }
  344. if inlined then
  345. para_offset:=pprocdef(p^.procdefinition)^.parast^.address_fixup+
  346. pprocdef(p^.procdefinition)^.parast^.datasize
  347. else
  348. para_offset:=0;
  349. if assigned(p^.right) then
  350. secondcallparan(p^.left,pabstractprocdef(p^.right^.resulttype)^.para1,
  351. (pocall_leftright in p^.procdefinition^.proccalloptions),
  352. inlined,
  353. (pocall_cdecl in p^.procdefinition^.proccalloptions) or
  354. (pocall_stdcall in p^.procdefinition^.proccalloptions),
  355. para_offset)
  356. else
  357. secondcallparan(p^.left,p^.procdefinition^.para1,
  358. (pocall_leftright in p^.procdefinition^.proccalloptions),
  359. inlined,
  360. (pocall_cdecl in p^.procdefinition^.proccalloptions) or
  361. (pocall_stdcall in p^.procdefinition^.proccalloptions),
  362. para_offset);
  363. end;
  364. params:=p^.left;
  365. p^.left:=nil;
  366. if inlined then
  367. inlinecode^.retoffset:=gettempofsizepersistant(4);
  368. if ret_in_param(p^.resulttype) then
  369. begin
  370. inc(pushedparasize,4);
  371. if inlined then
  372. begin
  373. emit_ref_reg(A_LEA,S_L,
  374. newreference(funcretref),R_EDI);
  375. r:=new_reference(procinfo.framepointer,inlinecode^.retoffset);
  376. emit_reg_ref(A_MOV,S_L,
  377. R_EDI,r);
  378. end
  379. else
  380. emitpushreferenceaddr(funcretref);
  381. end;
  382. { procedure variable ? }
  383. if (p^.right=nil) then
  384. begin
  385. { overloaded operator have no symtable }
  386. { push self }
  387. if assigned(p^.symtable) and
  388. (p^.symtable^.symtabletype=withsymtable) then
  389. begin
  390. { dirty trick to avoid the secondcall below }
  391. p^.methodpointer:=genzeronode(callparan);
  392. p^.methodpointer^.location.loc:=LOC_REGISTER;
  393. p^.methodpointer^.location.register:=R_ESI;
  394. { ARGHHH this is wrong !!!
  395. if we can init from base class for a child
  396. class that the wrong VMT will be
  397. transfered to constructor !! }
  398. p^.methodpointer^.resulttype:=
  399. ptree(pwithsymtable(p^.symtable)^.withnode)^.left^.resulttype;
  400. { change dispose type !! }
  401. p^.disposetyp:=dt_mbleft_and_method;
  402. { make a reference }
  403. new(r);
  404. reset_reference(r^);
  405. { if assigned(ptree(pwithsymtable(p^.symtable)^.withnode)^.pref) then
  406. begin
  407. r^:=ptree(pwithsymtable(p^.symtable)^.withnode)^.pref^;
  408. end
  409. else
  410. begin
  411. r^.offset:=p^.symtable^.datasize;
  412. r^.base:=procinfo.framepointer;
  413. end; }
  414. r^:=ptree(pwithsymtable(p^.symtable)^.withnode)^.withreference^;
  415. if (not pwithsymtable(p^.symtable)^.direct_with) or
  416. pobjectdef(p^.methodpointer^.resulttype)^.is_class then
  417. emit_ref_reg(A_MOV,S_L,r,R_ESI)
  418. else
  419. emit_ref_reg(A_LEA,S_L,r,R_ESI);
  420. end;
  421. { push self }
  422. if assigned(p^.symtable) and
  423. ((p^.symtable^.symtabletype=objectsymtable) or
  424. (p^.symtable^.symtabletype=withsymtable)) then
  425. begin
  426. if assigned(p^.methodpointer) then
  427. begin
  428. {
  429. if p^.methodpointer^.resulttype=classrefdef then
  430. begin
  431. two possibilities:
  432. 1. constructor
  433. 2. class method
  434. end
  435. else }
  436. begin
  437. case p^.methodpointer^.treetype of
  438. typen:
  439. begin
  440. { direct call to inherited method }
  441. if (po_abstractmethod in p^.procdefinition^.procoptions) then
  442. begin
  443. CGMessage(cg_e_cant_call_abstract_method);
  444. goto dont_call;
  445. end;
  446. { generate no virtual call }
  447. no_virtual_call:=true;
  448. if (sp_static in p^.symtableprocentry^.symoptions) then
  449. begin
  450. { well lets put the VMT address directly into ESI }
  451. { it is kind of dirty but that is the simplest }
  452. { way to accept virtual static functions (PM) }
  453. loadesi:=true;
  454. { if no VMT just use $0 bug0214 PM }
  455. if not(oo_has_vmt in pobjectdef(p^.methodpointer^.resulttype)^.objectoptions) then
  456. emit_const_reg(A_MOV,S_L,0,R_ESI)
  457. else
  458. begin
  459. emit_sym_ofs_reg(A_MOV,S_L,
  460. newasmsymbol(pobjectdef(p^.methodpointer^.resulttype)^.vmt_mangledname),
  461. 0,R_ESI);
  462. end;
  463. { emit_reg(A_PUSH,S_L,R_ESI);
  464. this is done below !! }
  465. end
  466. else
  467. { this is a member call, so ESI isn't modfied }
  468. loadesi:=false;
  469. { a class destructor needs a flag }
  470. if pobjectdef(p^.methodpointer^.resulttype)^.is_class and
  471. assigned(aktprocsym) and
  472. (aktprocsym^.definition^.proctypeoption=potype_destructor) then
  473. begin
  474. push_int(0);
  475. emit_reg(A_PUSH,S_L,R_ESI);
  476. end;
  477. if not(is_con_or_destructor and
  478. pobjectdef(p^.methodpointer^.resulttype)^.is_class and
  479. assigned(aktprocsym) and
  480. (aktprocsym^.definition^.proctypeoption in [potype_constructor,potype_destructor])
  481. ) then
  482. emit_reg(A_PUSH,S_L,R_ESI);
  483. { if an inherited con- or destructor should be }
  484. { called in a con- or destructor then a warning }
  485. { will be made }
  486. { con- and destructors need a pointer to the vmt }
  487. if is_con_or_destructor and
  488. not(pobjectdef(p^.methodpointer^.resulttype)^.is_class) and
  489. assigned(aktprocsym) then
  490. begin
  491. if not(aktprocsym^.definition^.proctypeoption in
  492. [potype_constructor,potype_destructor]) then
  493. CGMessage(cg_w_member_cd_call_from_method);
  494. end;
  495. { class destructors get there flag below }
  496. if is_con_or_destructor and
  497. not(pobjectdef(p^.methodpointer^.resulttype)^.is_class and
  498. assigned(aktprocsym) and
  499. (aktprocsym^.definition^.proctypeoption=potype_destructor)) then
  500. push_int(0);
  501. end;
  502. hnewn:
  503. begin
  504. { extended syntax of new }
  505. { ESI must be zero }
  506. emit_reg_reg(A_XOR,S_L,R_ESI,R_ESI);
  507. emit_reg(A_PUSH,S_L,R_ESI);
  508. { insert the vmt }
  509. emit_sym(A_PUSH,S_L,
  510. newasmsymbol(pobjectdef(p^.methodpointer^.resulttype)^.vmt_mangledname));
  511. extended_new:=true;
  512. end;
  513. hdisposen:
  514. begin
  515. secondpass(p^.methodpointer);
  516. { destructor with extended syntax called from dispose }
  517. { hdisposen always deliver LOC_REFERENCE }
  518. emit_ref_reg(A_LEA,S_L,
  519. newreference(p^.methodpointer^.location.reference),R_ESI);
  520. del_reference(p^.methodpointer^.location.reference);
  521. emit_reg(A_PUSH,S_L,R_ESI);
  522. emit_sym(A_PUSH,S_L,
  523. newasmsymbol(pobjectdef(p^.methodpointer^.resulttype)^.vmt_mangledname));
  524. end;
  525. else
  526. begin
  527. { call to an instance member }
  528. if (p^.symtable^.symtabletype<>withsymtable) then
  529. begin
  530. secondpass(p^.methodpointer);
  531. case p^.methodpointer^.location.loc of
  532. LOC_CREGISTER,
  533. LOC_REGISTER:
  534. begin
  535. emit_reg_reg(A_MOV,S_L,p^.methodpointer^.location.register,R_ESI);
  536. ungetregister32(p^.methodpointer^.location.register);
  537. end;
  538. else
  539. begin
  540. if (p^.methodpointer^.resulttype^.deftype=classrefdef) or
  541. ((p^.methodpointer^.resulttype^.deftype=objectdef) and
  542. pobjectdef(p^.methodpointer^.resulttype)^.is_class) then
  543. emit_ref_reg(A_MOV,S_L,
  544. newreference(p^.methodpointer^.location.reference),R_ESI)
  545. else
  546. emit_ref_reg(A_LEA,S_L,
  547. newreference(p^.methodpointer^.location.reference),R_ESI);
  548. del_reference(p^.methodpointer^.location.reference);
  549. end;
  550. end;
  551. end;
  552. { when calling a class method, we have to load ESI with the VMT !
  553. But, not for a class method via self }
  554. if not(po_containsself in p^.procdefinition^.procoptions) then
  555. begin
  556. if (po_classmethod in p^.procdefinition^.procoptions) and
  557. not(p^.methodpointer^.resulttype^.deftype=classrefdef) then
  558. begin
  559. { class method needs current VMT }
  560. new(r);
  561. reset_reference(r^);
  562. r^.base:=R_ESI;
  563. r^.offset:= pprocdef(p^.procdefinition)^._class^.vmt_offset;
  564. emit_ref_reg(A_MOV,S_L,r,R_ESI);
  565. end;
  566. { direct call to destructor: don't remove data! }
  567. if (p^.procdefinition^.proctypeoption=potype_destructor) and
  568. (p^.methodpointer^.resulttype^.deftype=objectdef) and
  569. (pobjectdef(p^.methodpointer^.resulttype)^.is_class) then
  570. emit_const(A_PUSH,S_L,1);
  571. { direct call to class constructor, don't allocate memory }
  572. if (p^.procdefinition^.proctypeoption=potype_constructor) and
  573. (p^.methodpointer^.resulttype^.deftype=objectdef) and
  574. (pobjectdef(p^.methodpointer^.resulttype)^.is_class) then
  575. emit_const(A_PUSH,S_L,0)
  576. else
  577. emit_reg(A_PUSH,S_L,R_ESI);
  578. end;
  579. if is_con_or_destructor then
  580. begin
  581. { classes don't get a VMT pointer pushed }
  582. if (p^.methodpointer^.resulttype^.deftype=objectdef) and
  583. not(pobjectdef(p^.methodpointer^.resulttype)^.is_class) then
  584. begin
  585. if (p^.procdefinition^.proctypeoption=potype_constructor) then
  586. begin
  587. { it's no bad idea, to insert the VMT }
  588. emit_sym(A_PUSH,S_L,newasmsymbol(
  589. pobjectdef(p^.methodpointer^.resulttype)^.vmt_mangledname));
  590. end
  591. { destructors haven't to dispose the instance, if this is }
  592. { a direct call }
  593. else
  594. push_int(0);
  595. end;
  596. end;
  597. end;
  598. end;
  599. end;
  600. end
  601. else
  602. begin
  603. if (po_classmethod in p^.procdefinition^.procoptions) and
  604. not(
  605. assigned(aktprocsym) and
  606. (po_classmethod in aktprocsym^.definition^.procoptions)
  607. ) then
  608. begin
  609. { class method needs current VMT }
  610. new(r);
  611. reset_reference(r^);
  612. r^.base:=R_ESI;
  613. r^.offset:= pprocdef(p^.procdefinition)^._class^.vmt_offset;
  614. emit_ref_reg(A_MOV,S_L,r,R_ESI);
  615. end
  616. else
  617. begin
  618. { member call, ESI isn't modified }
  619. loadesi:=false;
  620. end;
  621. emit_reg(A_PUSH,S_L,R_ESI);
  622. { but a con- or destructor here would probably almost }
  623. { always be placed wrong }
  624. if is_con_or_destructor then
  625. begin
  626. CGMessage(cg_w_member_cd_call_from_method);
  627. push_int(0);
  628. end;
  629. end;
  630. end;
  631. { push base pointer ?}
  632. if (lexlevel>=normal_function_level) and assigned(pprocdef(p^.procdefinition)^.parast) and
  633. ((pprocdef(p^.procdefinition)^.parast^.symtablelevel)>normal_function_level) then
  634. begin
  635. { if we call a nested function in a method, we must }
  636. { push also SELF! }
  637. { THAT'S NOT TRUE, we have to load ESI via frame pointer }
  638. { access }
  639. {
  640. begin
  641. loadesi:=false;
  642. emit_reg(A_PUSH,S_L,R_ESI);
  643. end;
  644. }
  645. if lexlevel=(pprocdef(p^.procdefinition)^.parast^.symtablelevel) then
  646. begin
  647. new(r);
  648. reset_reference(r^);
  649. r^.offset:=procinfo.framepointer_offset;
  650. r^.base:=procinfo.framepointer;
  651. emit_ref(A_PUSH,S_L,r)
  652. end
  653. { this is only true if the difference is one !!
  654. but it cannot be more !! }
  655. else if (lexlevel=pprocdef(p^.procdefinition)^.parast^.symtablelevel-1) then
  656. begin
  657. emit_reg(A_PUSH,S_L,procinfo.framepointer)
  658. end
  659. else if (lexlevel>pprocdef(p^.procdefinition)^.parast^.symtablelevel) then
  660. begin
  661. hregister:=getregister32;
  662. new(r);
  663. reset_reference(r^);
  664. r^.offset:=procinfo.framepointer_offset;
  665. r^.base:=procinfo.framepointer;
  666. emit_ref_reg(A_MOV,S_L,r,hregister);
  667. for i:=(pprocdef(p^.procdefinition)^.parast^.symtablelevel) to lexlevel-1 do
  668. begin
  669. new(r);
  670. reset_reference(r^);
  671. {we should get the correct frame_pointer_offset at each level
  672. how can we do this !!! }
  673. r^.offset:=procinfo.framepointer_offset;
  674. r^.base:=hregister;
  675. emit_ref_reg(A_MOV,S_L,r,hregister);
  676. end;
  677. emit_reg(A_PUSH,S_L,hregister);
  678. ungetregister32(hregister);
  679. end
  680. else
  681. internalerror(25000);
  682. end;
  683. if (po_virtualmethod in p^.procdefinition^.procoptions) and
  684. not(no_virtual_call) then
  685. begin
  686. { static functions contain the vmt_address in ESI }
  687. { also class methods }
  688. { Here it is quite tricky because it also depends }
  689. { on the methodpointer PM }
  690. if assigned(aktprocsym) then
  691. begin
  692. if (((sp_static in aktprocsym^.symoptions) or
  693. (po_classmethod in aktprocsym^.definition^.procoptions)) and
  694. ((p^.methodpointer=nil) or (p^.methodpointer^.treetype=typen)))
  695. or
  696. (po_staticmethod in p^.procdefinition^.procoptions) or
  697. (p^.procdefinition^.proctypeoption=potype_constructor) or
  698. { ESI is loaded earlier }
  699. (po_classmethod in p^.procdefinition^.procoptions) then
  700. begin
  701. new(r);
  702. reset_reference(r^);
  703. r^.base:=R_ESI;
  704. end
  705. else
  706. begin
  707. new(r);
  708. reset_reference(r^);
  709. r^.base:=R_ESI;
  710. { this is one point where we need vmt_offset (PM) }
  711. r^.offset:= pprocdef(p^.procdefinition)^._class^.vmt_offset;
  712. emit_ref_reg(A_MOV,S_L,r,R_EDI);
  713. new(r);
  714. reset_reference(r^);
  715. r^.base:=R_EDI;
  716. end;
  717. end
  718. else
  719. { aktprocsym should be assigned, also in main program }
  720. internalerror(12345);
  721. {
  722. begin
  723. new(r);
  724. reset_reference(r^);
  725. r^.base:=R_ESI;
  726. emit_ref_reg(A_MOV,S_L,r,R_EDI);
  727. new(r);
  728. reset_reference(r^);
  729. r^.base:=R_EDI;
  730. end;
  731. }
  732. if pprocdef(p^.procdefinition)^.extnumber=-1 then
  733. internalerror(44584);
  734. r^.offset:=pprocdef(p^.procdefinition)^._class^.vmtmethodoffset(pprocdef(p^.procdefinition)^.extnumber);
  735. {$ifndef TESTOBJEXT}
  736. if (cs_check_range in aktlocalswitches) then
  737. begin
  738. emit_reg(A_PUSH,S_L,r^.base);
  739. emitcall('FPC_CHECK_OBJECT');
  740. end;
  741. {$else TESTOBJEXT}
  742. if (cs_check_range in aktlocalswitches) then
  743. begin
  744. emit_sym(A_PUSH,S_L,
  745. newasmsymbol(pprocdef(p^.procdefinition)^._class^.vmt_mangledname));
  746. emit_reg(A_PUSH,S_L,r^.base);
  747. emitcall('FPC_CHECK_OBJECT_EXT');
  748. end;
  749. {$endif TESTOBJEXT}
  750. emit_ref(A_CALL,S_NO,r);
  751. end
  752. else if not inlined then
  753. emitcall(pprocdef(p^.procdefinition)^.mangledname)
  754. else { inlined proc }
  755. { inlined code is in inlinecode }
  756. begin
  757. { set poinline again }
  758. {$ifdef INCLUDEOK}
  759. include(p^.procdefinition^.proccalloptions,pocall_inline);
  760. {$else}
  761. p^.procdefinition^.proccalloptions:=p^.procdefinition^.proccalloptions+[pocall_inline];
  762. {$endif}
  763. { process the inlinecode }
  764. secondpass(inlinecode);
  765. { free the args }
  766. ungetpersistanttemp(pprocdef(p^.procdefinition)^.parast^.address_fixup);
  767. end;
  768. end
  769. else
  770. { now procedure variable case }
  771. begin
  772. secondpass(p^.right);
  773. { procedure of object? }
  774. if (po_methodpointer in p^.procdefinition^.procoptions) then
  775. begin
  776. { method pointer can't be in a register }
  777. hregister:=R_NO;
  778. { do some hacking if we call a method pointer }
  779. { which is a class member }
  780. { else ESI is overwritten ! }
  781. if (p^.right^.location.reference.base=R_ESI) or
  782. (p^.right^.location.reference.index=R_ESI) then
  783. begin
  784. del_reference(p^.right^.location.reference);
  785. emit_ref_reg(A_MOV,S_L,
  786. newreference(p^.right^.location.reference),R_EDI);
  787. hregister:=R_EDI;
  788. end;
  789. { load self, but not if it's already explicitly pushed }
  790. if not(po_containsself in p^.procdefinition^.procoptions) then
  791. begin
  792. { load ESI }
  793. inc(p^.right^.location.reference.offset,4);
  794. emit_ref_reg(A_MOV,S_L,
  795. newreference(p^.right^.location.reference),R_ESI);
  796. dec(p^.right^.location.reference.offset,4);
  797. { push self pointer }
  798. emit_reg(A_PUSH,S_L,R_ESI);
  799. end;
  800. if hregister=R_NO then
  801. emit_ref(A_CALL,S_NO,newreference(p^.right^.location.reference))
  802. else
  803. emit_reg(A_CALL,S_NO,hregister);
  804. del_reference(p^.right^.location.reference);
  805. end
  806. else
  807. begin
  808. case p^.right^.location.loc of
  809. LOC_REGISTER,LOC_CREGISTER:
  810. begin
  811. emit_reg(A_CALL,S_NO,p^.right^.location.register);
  812. ungetregister32(p^.right^.location.register);
  813. end
  814. else
  815. emit_ref(A_CALL,S_NO,newreference(p^.right^.location.reference));
  816. del_reference(p^.right^.location.reference);
  817. end;
  818. end;
  819. end;
  820. { this was only for normal functions
  821. displaced here so we also get
  822. it to work for procvars PM }
  823. if (not inlined) and (pocall_clearstack in p^.procdefinition^.proccalloptions) then
  824. begin
  825. { consider the alignment with the rest (PM) }
  826. inc(pushedparasize,pop_size);
  827. pop_size:=0;
  828. { better than an add on all processors }
  829. if pushedparasize=4 then
  830. emit_reg(A_POP,S_L,R_EDI)
  831. { the pentium has two pipes and pop reg is pairable }
  832. { but the registers must be different! }
  833. else if (pushedparasize=8) and
  834. not(cs_littlesize in aktglobalswitches) and
  835. (aktoptprocessor=ClassP5) and
  836. (procinfo._class=nil) then
  837. begin
  838. emit_reg(A_POP,S_L,R_EDI);
  839. emit_reg(A_POP,S_L,R_ESI);
  840. end
  841. else if pushedparasize<>0 then
  842. emit_const_reg(A_ADD,S_L,pushedparasize,R_ESP);
  843. end;
  844. dont_call:
  845. pushedparasize:=oldpushedparasize;
  846. unused:=unusedregisters;
  847. { a constructor could be a function with boolean result }
  848. { if calling constructor called fail we
  849. must jump directly to quickexitlabel PM
  850. but only if it is a call of an inherited constructor }
  851. if (p^.right=nil) and
  852. (p^.procdefinition^.proctypeoption=potype_constructor) and
  853. assigned(p^.methodpointer) and
  854. (p^.methodpointer^.treetype=typen) and
  855. (aktprocsym^.definition^.proctypeoption=potype_constructor) then
  856. begin
  857. emitjmp(C_Z,faillabel);
  858. end;
  859. { handle function results }
  860. { structured results are easy to handle.... }
  861. { needed also when result_no_used !! }
  862. if (p^.resulttype<>pdef(voiddef)) and ret_in_param(p^.resulttype) then
  863. begin
  864. p^.location.loc:=LOC_MEM;
  865. p^.location.reference.symbol:=nil;
  866. p^.location.reference:=funcretref;
  867. end;
  868. { we have only to handle the result if it is used, but }
  869. { ansi/widestrings must be registered, so we can dispose them }
  870. if (p^.resulttype<>pdef(voiddef)) and (p^.return_value_used or
  871. is_ansistring(p^.resulttype) or is_widestring(p^.resulttype)) then
  872. begin
  873. { a contructor could be a function with boolean result }
  874. if (p^.right=nil) and
  875. (p^.procdefinition^.proctypeoption=potype_constructor) and
  876. { quick'n'dirty check if it is a class or an object }
  877. (p^.resulttype^.deftype=orddef) then
  878. begin
  879. { this fails if popsize > 0 PM }
  880. p^.location.loc:=LOC_FLAGS;
  881. p^.location.resflags:=F_NE;
  882. if extended_new then
  883. begin
  884. {$ifdef test_dest_loc}
  885. if dest_loc_known and (dest_loc_tree=p) then
  886. mov_reg_to_dest(p,S_L,R_EAX)
  887. else
  888. {$endif test_dest_loc}
  889. begin
  890. hregister:=getexplicitregister32(R_EAX);
  891. emit_reg_reg(A_MOV,S_L,R_EAX,hregister);
  892. p^.location.register:=hregister;
  893. end;
  894. end;
  895. end
  896. { structed results are easy to handle.... }
  897. else if ret_in_param(p^.resulttype) then
  898. begin
  899. {p^.location.loc:=LOC_MEM;
  900. stringdispose(p^.location.reference.symbol);
  901. p^.location.reference:=funcretref;
  902. already done above (PM) }
  903. end
  904. else
  905. begin
  906. if (p^.resulttype^.deftype in [orddef,enumdef]) then
  907. begin
  908. p^.location.loc:=LOC_REGISTER;
  909. case p^.resulttype^.size of
  910. 4 :
  911. begin
  912. {$ifdef test_dest_loc}
  913. if dest_loc_known and (dest_loc_tree=p) then
  914. mov_reg_to_dest(p,S_L,R_EAX)
  915. else
  916. {$endif test_dest_loc}
  917. begin
  918. hregister:=getexplicitregister32(R_EAX);
  919. emit_reg_reg(A_MOV,S_L,R_EAX,hregister);
  920. p^.location.register:=hregister;
  921. end;
  922. end;
  923. 1 :
  924. begin
  925. {$ifdef test_dest_loc}
  926. if dest_loc_known and (dest_loc_tree=p) then
  927. mov_reg_to_dest(p,S_B,R_AL)
  928. else
  929. {$endif test_dest_loc}
  930. begin
  931. hregister:=getexplicitregister32(R_EAX);
  932. emit_reg_reg(A_MOV,S_B,R_AL,reg32toreg8(hregister));
  933. p^.location.register:=reg32toreg8(hregister);
  934. end;
  935. end;
  936. 2 :
  937. begin
  938. {$ifdef test_dest_loc}
  939. if dest_loc_known and (dest_loc_tree=p) then
  940. mov_reg_to_dest(p,S_W,R_AX)
  941. else
  942. {$endif test_dest_loc}
  943. begin
  944. hregister:=getexplicitregister32(R_EAX);
  945. emit_reg_reg(A_MOV,S_W,R_AX,reg32toreg16(hregister));
  946. p^.location.register:=reg32toreg16(hregister);
  947. end;
  948. end;
  949. 8 :
  950. begin
  951. {$ifdef test_dest_loc}
  952. {$error Don't know what to do here}
  953. {$endif test_dest_loc}
  954. hregister:=getexplicitregister32(R_EAX);
  955. hregister2:=getexplicitregister32(R_EDX);
  956. emit_reg_reg(A_MOV,S_L,R_EAX,hregister);
  957. emit_reg_reg(A_MOV,S_L,R_EDX,hregister2);
  958. p^.location.registerlow:=hregister;
  959. p^.location.registerhigh:=hregister2;
  960. end;
  961. else internalerror(7);
  962. end
  963. end
  964. else if (p^.resulttype^.deftype=floatdef) then
  965. case pfloatdef(p^.resulttype)^.typ of
  966. f32bit:
  967. begin
  968. p^.location.loc:=LOC_REGISTER;
  969. {$ifdef test_dest_loc}
  970. if dest_loc_known and (dest_loc_tree=p) then
  971. mov_reg_to_dest(p,S_L,R_EAX)
  972. else
  973. {$endif test_dest_loc}
  974. begin
  975. hregister:=getexplicitregister32(R_EAX);
  976. emit_reg_reg(A_MOV,S_L,R_EAX,hregister);
  977. p^.location.register:=hregister;
  978. end;
  979. end;
  980. else
  981. begin
  982. p^.location.loc:=LOC_FPU;
  983. inc(fpuvaroffset);
  984. end;
  985. end
  986. else if is_ansistring(p^.resulttype) or
  987. is_widestring(p^.resulttype) then
  988. begin
  989. hregister:=getexplicitregister32(R_EAX);
  990. emit_reg_reg(A_MOV,S_L,R_EAX,hregister);
  991. if gettempansistringreference(hr) then
  992. decrstringref(p^.resulttype,hr);
  993. emit_reg_ref(A_MOV,S_L,hregister,
  994. newreference(hr));
  995. ungetregister32(hregister);
  996. p^.location.loc:=LOC_MEM;
  997. p^.location.reference:=hr;
  998. end
  999. else
  1000. begin
  1001. p^.location.loc:=LOC_REGISTER;
  1002. {$ifdef test_dest_loc}
  1003. if dest_loc_known and (dest_loc_tree=p) then
  1004. mov_reg_to_dest(p,S_L,R_EAX)
  1005. else
  1006. {$endif test_dest_loc}
  1007. begin
  1008. hregister:=getexplicitregister32(R_EAX);
  1009. emit_reg_reg(A_MOV,S_L,R_EAX,hregister);
  1010. p^.location.register:=hregister;
  1011. end;
  1012. end;
  1013. end;
  1014. end;
  1015. { perhaps i/o check ? }
  1016. if iolabel<>nil then
  1017. begin
  1018. emit_sym(A_PUSH,S_L,iolabel);
  1019. emitcall('FPC_IOCHECK');
  1020. end;
  1021. if pop_size>0 then
  1022. emit_const_reg(A_ADD,S_L,pop_size,R_ESP);
  1023. { restore registers }
  1024. popusedregisters(pushed);
  1025. { at last, restore instance pointer (SELF) }
  1026. if loadesi then
  1027. maybe_loadesi;
  1028. pp:=params;
  1029. while assigned(pp) do
  1030. begin
  1031. if assigned(pp^.left) then
  1032. begin
  1033. if (pp^.left^.location.loc in [LOC_REFERENCE,LOC_MEM]) then
  1034. ungetiftemp(pp^.left^.location.reference);
  1035. { process also all nodes of an array of const }
  1036. if pp^.left^.treetype=arrayconstructn then
  1037. begin
  1038. if assigned(pp^.left^.left) then
  1039. begin
  1040. hp:=pp^.left;
  1041. while assigned(hp) do
  1042. begin
  1043. if (hp^.left^.location.loc in [LOC_REFERENCE,LOC_MEM]) then
  1044. ungetiftemp(hp^.left^.location.reference);
  1045. hp:=hp^.right;
  1046. end;
  1047. end;
  1048. end;
  1049. end;
  1050. pp:=pp^.right;
  1051. end;
  1052. if inlined then
  1053. ungetpersistanttemp(inlinecode^.retoffset);
  1054. disposetree(params);
  1055. { from now on the result can be freed normally }
  1056. if inlined and ret_in_param(p^.resulttype) then
  1057. persistanttemptonormal(funcretref.offset);
  1058. { if return value is not used }
  1059. if (not p^.return_value_used) and (p^.resulttype<>pdef(voiddef)) then
  1060. begin
  1061. if p^.location.loc in [LOC_MEM,LOC_REFERENCE] then
  1062. begin
  1063. { data which must be finalized ? }
  1064. if (p^.resulttype^.needs_inittable) and
  1065. ( (p^.resulttype^.deftype<>objectdef) or
  1066. not(pobjectdef(p^.resulttype)^.is_class)) then
  1067. finalize(p^.resulttype,p^.location.reference,ret_in_param(p^.resulttype));
  1068. { release unused temp }
  1069. ungetiftemp(p^.location.reference)
  1070. end
  1071. else if p^.location.loc=LOC_FPU then
  1072. begin
  1073. { release FPU stack }
  1074. emit_reg(A_FSTP,S_NO,R_ST0);
  1075. dec(fpuvaroffset);
  1076. end;
  1077. end;
  1078. end;
  1079. {*****************************************************************************
  1080. SecondProcInlineN
  1081. *****************************************************************************}
  1082. procedure secondprocinline(var p : ptree);
  1083. var st : psymtable;
  1084. oldprocsym : pprocsym;
  1085. para_size : longint;
  1086. oldprocinfo : tprocinfo;
  1087. { just dummies for genentrycode }
  1088. nostackframe,make_global : boolean;
  1089. proc_names : tstringcontainer;
  1090. inlineentrycode,inlineexitcode : paasmoutput;
  1091. oldexitlabel,oldexit2label,oldquickexitlabel:Pasmlabel;
  1092. begin
  1093. oldexitlabel:=aktexitlabel;
  1094. oldexit2label:=aktexit2label;
  1095. oldquickexitlabel:=quickexitlabel;
  1096. getlabel(aktexitlabel);
  1097. getlabel(aktexit2label);
  1098. oldprocsym:=aktprocsym;
  1099. oldprocinfo:=procinfo;
  1100. { set the return value }
  1101. aktprocsym:=p^.inlineprocsym;
  1102. procinfo.retdef:=aktprocsym^.definition^.retdef;
  1103. procinfo.retoffset:=p^.retoffset;
  1104. { arg space has been filled by the parent secondcall }
  1105. st:=aktprocsym^.definition^.localst;
  1106. { set it to the same lexical level }
  1107. st^.symtablelevel:=oldprocsym^.definition^.localst^.symtablelevel;
  1108. if st^.datasize>0 then
  1109. begin
  1110. st^.address_fixup:=gettempofsizepersistant(st^.datasize);
  1111. {$ifdef extdebug}
  1112. Comment(V_debug,'local symtable is at offset '+tostr(st^.address_fixup));
  1113. exprasmlist^.concat(new(pai_asm_comment,init(strpnew(
  1114. 'local symtable is at offset '+tostr(st^.address_fixup)))));
  1115. {$endif extdebug}
  1116. end;
  1117. {$ifdef extdebug}
  1118. exprasmlist^.concat(new(pai_asm_comment,init('Start of inlined proc')));
  1119. {$endif extdebug}
  1120. { takes care of local data initialization }
  1121. inlineentrycode:=new(paasmoutput,init);
  1122. inlineexitcode:=new(paasmoutput,init);
  1123. proc_names.init;
  1124. para_size:=p^.para_size;
  1125. make_global:=false; { to avoid warning }
  1126. genentrycode(inlineentrycode,proc_names,make_global,0,para_size,nostackframe,true);
  1127. exprasmlist^.concatlist(inlineentrycode);
  1128. secondpass(p^.inlinetree);
  1129. genexitcode(inlineexitcode,0,false,true);
  1130. exprasmlist^.concatlist(inlineexitcode);
  1131. {$ifdef extdebug}
  1132. exprasmlist^.concat(new(pai_asm_comment,init('End of inlined proc')));
  1133. {$endif extdebug}
  1134. {we can free the local data now, reset also the fixup address }
  1135. if st^.datasize>0 then
  1136. begin
  1137. ungetpersistanttemp(st^.address_fixup);
  1138. st^.address_fixup:=0;
  1139. end;
  1140. aktprocsym:=oldprocsym;
  1141. freelabel(aktexitlabel);
  1142. freelabel(aktexit2label);
  1143. aktexitlabel:=oldexitlabel;
  1144. aktexit2label:=oldexit2label;
  1145. quickexitlabel:=oldquickexitlabel;
  1146. procinfo:=oldprocinfo;
  1147. end;
  1148. end.
  1149. {
  1150. $Log$
  1151. Revision 1.100 1999-08-19 13:08:45 pierre
  1152. * emit_??? used
  1153. Revision 1.99 1999/08/09 22:19:47 peter
  1154. * classes vmt changed to only positive addresses
  1155. * sharedlib creation is working
  1156. Revision 1.98 1999/08/09 10:37:55 peter
  1157. * fixed pushing of self with methodpointer
  1158. Revision 1.97 1999/08/04 13:45:18 florian
  1159. + floating point register variables !!
  1160. * pairegalloc is now generated for register variables
  1161. Revision 1.96 1999/08/04 00:22:41 florian
  1162. * renamed i386asm and i386base to cpuasm and cpubase
  1163. Revision 1.95 1999/08/03 22:02:34 peter
  1164. * moved bitmask constants to sets
  1165. * some other type/const renamings
  1166. Revision 1.94 1999/07/06 21:48:09 florian
  1167. * a lot bug fixes:
  1168. - po_external isn't any longer necessary for procedure compatibility
  1169. - m_tp_procvar is in -Sd now available
  1170. - error messages of procedure variables improved
  1171. - return values with init./finalization fixed
  1172. - data types with init./finalization aren't any longer allowed in variant
  1173. record
  1174. Revision 1.93 1999/06/22 13:31:24 peter
  1175. * merged
  1176. Revision 1.92 1999/06/16 09:32:45 peter
  1177. * merged
  1178. Revision 1.91 1999/06/14 17:47:47 peter
  1179. * merged
  1180. Revision 1.90.2.3 1999/06/22 13:30:08 peter
  1181. * fixed return with packenum
  1182. Revision 1.90.2.2 1999/06/16 09:30:44 peter
  1183. * fixed loading of ansistring when eax was already used
  1184. Revision 1.90.2.1 1999/06/14 17:24:42 peter
  1185. * fixed saving of registers with decr_ansistr
  1186. Revision 1.90 1999/06/02 10:11:40 florian
  1187. * make cycle fixed i.e. compilation with 0.99.10
  1188. * some fixes for qword
  1189. * start of register calling conventions
  1190. Revision 1.89 1999/05/28 15:59:46 pierre
  1191. * forgotten emitcall change in conditionnal
  1192. Revision 1.88 1999/05/28 11:00:49 peter
  1193. * removed ungettempoftype
  1194. Revision 1.87 1999/05/27 19:44:07 peter
  1195. * removed oldasm
  1196. * plabel -> pasmlabel
  1197. * -a switches to source writing automaticly
  1198. * assembler readers OOPed
  1199. * asmsymbol automaticly external
  1200. * jumptables and other label fixes for asm readers
  1201. Revision 1.86 1999/05/23 18:41:58 florian
  1202. * better error recovering in typed constants
  1203. * some problems with arrays of const fixed, some problems
  1204. due my previous
  1205. - the location type of array constructor is now LOC_MEM
  1206. - the pushing of high fixed
  1207. - parameter copying fixed
  1208. - zero temp. allocation removed
  1209. * small problem in the assembler writers fixed:
  1210. ref to nil wasn't written correctly
  1211. Revision 1.85 1999/05/21 13:54:44 peter
  1212. * NEWLAB for label as symbol
  1213. Revision 1.84 1999/05/18 22:34:26 pierre
  1214. * extedebug problem solved
  1215. Revision 1.83 1999/05/18 21:58:24 florian
  1216. * fixed some bugs related to temp. ansistrings and functions results
  1217. which return records/objects/arrays which need init/final.
  1218. Revision 1.82 1999/05/18 14:15:23 peter
  1219. * containsself fixes
  1220. * checktypes()
  1221. Revision 1.81 1999/05/18 09:52:17 peter
  1222. * procedure of object and addrn fixes
  1223. Revision 1.80 1999/05/17 23:51:37 peter
  1224. * with temp vars now use a reference with a persistant temp instead
  1225. of setting datasize
  1226. Revision 1.79 1999/05/17 21:56:59 florian
  1227. * new temporary ansistring handling
  1228. Revision 1.78 1999/05/01 13:24:02 peter
  1229. * merged nasm compiler
  1230. * old asm moved to oldasm/
  1231. Revision 1.77 1999/04/29 22:12:21 pierre
  1232. * fix for ID 388 removing real from stack was wrong
  1233. Revision 1.76 1999/04/25 22:33:19 pierre
  1234. * fix for TESTOBJEXT code
  1235. Revision 1.75 1999/04/19 09:45:46 pierre
  1236. + cdecl or stdcall push all args with longint size
  1237. * tempansi stuff cleaned up
  1238. Revision 1.74 1999/04/16 13:42:23 jonas
  1239. * more regalloc fixes (still not complete)
  1240. Revision 1.73 1999/04/16 10:26:56 pierre
  1241. * no add $0,%esp for cdecl functions without parameters
  1242. Revision 1.72 1999/04/09 08:41:48 peter
  1243. * define to get ansistring returns in ref instead of reg
  1244. Revision 1.71 1999/03/31 13:55:04 peter
  1245. * assembler inlining working for ag386bin
  1246. Revision 1.70 1999/03/24 23:16:46 peter
  1247. * fixed bugs 212,222,225,227,229,231,233
  1248. Revision 1.69 1999/02/25 21:02:21 peter
  1249. * ag386bin updates
  1250. + coff writer
  1251. Revision 1.68 1999/02/22 02:15:04 peter
  1252. * updates for ag386bin
  1253. Revision 1.67 1999/02/11 09:46:21 pierre
  1254. * fix for normal method calls inside static methods :
  1255. WARNING there were both parser and codegen errors !!
  1256. added static_call boolean to calln tree
  1257. Revision 1.66 1999/02/09 15:45:46 florian
  1258. + complex results for assembler functions, fixes bug0155
  1259. Revision 1.65 1999/02/08 11:29:04 pierre
  1260. * fix for bug0214
  1261. several problems where combined
  1262. search_class_member did not set srsymtable
  1263. => in do_member_read the call node got a wrong symtable
  1264. in cg386cal the vmt was pushed twice without chacking if it exists
  1265. now %esi is set to zero and pushed if not vmt
  1266. (not very efficient but should work !)
  1267. Revision 1.64 1999/02/04 10:49:39 florian
  1268. + range checking for ansi- and widestrings
  1269. * made it compilable with TP
  1270. Revision 1.63 1999/02/03 10:18:14 pierre
  1271. * conditionnal code for extended check of virtual methods
  1272. Revision 1.62 1999/02/02 23:52:32 florian
  1273. * problem with calls to method pointers in methods fixed
  1274. - double ansistrings temp management removed
  1275. Revision 1.61 1999/02/02 11:04:36 florian
  1276. * class destructors fixed, class instances weren't disposed correctly
  1277. Revision 1.60 1999/01/28 23:56:44 florian
  1278. * the reference in the result location of a function call wasn't resetted =>
  1279. problem with unallowed far pointer, is solved now
  1280. Revision 1.59 1999/01/27 00:13:52 florian
  1281. * "procedure of object"-stuff fixed
  1282. Revision 1.58 1999/01/21 22:10:35 peter
  1283. * fixed array of const
  1284. * generic platform independent high() support
  1285. Revision 1.57 1999/01/21 16:40:51 pierre
  1286. * fix for constructor inside with statements
  1287. Revision 1.56 1998/12/30 13:41:05 peter
  1288. * released valuepara
  1289. Revision 1.55 1998/12/22 13:10:58 florian
  1290. * memory leaks for ansistring type casts fixed
  1291. Revision 1.54 1998/12/19 00:23:41 florian
  1292. * ansistring memory leaks fixed
  1293. Revision 1.53 1998/12/11 00:02:47 peter
  1294. + globtype,tokens,version unit splitted from globals
  1295. Revision 1.52 1998/12/10 14:39:29 florian
  1296. * bug with p(const a : ansistring) fixed
  1297. * duplicate constant ansistrings were handled wrong, fixed
  1298. Revision 1.51 1998/12/10 09:47:15 florian
  1299. + basic operations with int64/qord (compiler with -dint64)
  1300. + rtti of enumerations extended: names are now written
  1301. Revision 1.50 1998/12/06 13:12:44 florian
  1302. * better code generation for classes which are passed as parameters to
  1303. subroutines
  1304. Revision 1.49 1998/11/30 09:43:00 pierre
  1305. * some range check bugs fixed (still not working !)
  1306. + added DLL writing support for win32 (also accepts variables)
  1307. + TempAnsi for code that could be used for Temporary ansi strings
  1308. handling
  1309. Revision 1.48 1998/11/27 14:50:30 peter
  1310. + open strings, $P switch support
  1311. Revision 1.47 1998/11/26 21:30:03 peter
  1312. * fix for valuepara
  1313. Revision 1.46 1998/11/26 14:39:10 peter
  1314. * ansistring -> pchar fixed
  1315. * ansistring constants fixed
  1316. * ansistring constants are now written once
  1317. Revision 1.45 1998/11/18 15:44:07 peter
  1318. * VALUEPARA for tp7 compatible value parameters
  1319. Revision 1.44 1998/11/16 15:35:36 peter
  1320. * rename laod/copystring -> load/copyshortstring
  1321. * fixed int-bool cnv bug
  1322. + char-ansistring conversion
  1323. Revision 1.43 1998/11/15 16:32:33 florian
  1324. * some stuff of Pavel implement (win32 dll creation)
  1325. * bug with ansistring function results fixed
  1326. Revision 1.42 1998/11/13 15:40:13 pierre
  1327. + added -Se in Makefile cvstest target
  1328. + lexlevel cleanup
  1329. normal_function_level main_program_level and unit_init_level defined
  1330. * tins_cache grown to A_EMMS (gave range check error in asm readers)
  1331. (test added in code !)
  1332. * -Un option was wrong
  1333. * _FAIL and _SELF only keyword inside
  1334. constructors and methods respectively
  1335. Revision 1.41 1998/11/12 11:19:40 pierre
  1336. * fix for first line of function break
  1337. Revision 1.40 1998/11/10 10:09:08 peter
  1338. * va_list -> array of const
  1339. Revision 1.39 1998/11/09 11:44:33 peter
  1340. + va_list for printf support
  1341. Revision 1.38 1998/10/21 15:12:49 pierre
  1342. * bug fix for IOCHECK inside a procedure with iocheck modifier
  1343. * removed the GPF for unexistant overloading
  1344. (firstcall was called with procedinition=nil !)
  1345. * changed typen to what Florian proposed
  1346. gentypenode(p : pdef) sets the typenodetype field
  1347. and resulttype is only set if inside bt_type block !
  1348. Revision 1.37 1998/10/21 08:39:57 florian
  1349. + ansistring operator +
  1350. + $h and string[n] for n>255 added
  1351. * small problem with TP fixed
  1352. Revision 1.36 1998/10/20 08:06:39 pierre
  1353. * several memory corruptions due to double freemem solved
  1354. => never use p^.loc.location:=p^.left^.loc.location;
  1355. + finally I added now by default
  1356. that ra386dir translates global and unit symbols
  1357. + added a first field in tsymtable and
  1358. a nextsym field in tsym
  1359. (this allows to obtain ordered type info for
  1360. records and objects in gdb !)
  1361. Revision 1.35 1998/10/16 08:51:45 peter
  1362. + target_os.stackalignment
  1363. + stack can be aligned at 2 or 4 byte boundaries
  1364. Revision 1.34 1998/10/09 08:56:22 pierre
  1365. * several memory leaks fixed
  1366. Revision 1.33 1998/10/06 17:16:39 pierre
  1367. * some memory leaks fixed (thanks to Peter for heaptrc !)
  1368. Revision 1.32 1998/10/01 09:22:52 peter
  1369. * fixed value openarray
  1370. * ungettemp of arrayconstruct
  1371. Revision 1.31 1998/09/28 16:57:15 pierre
  1372. * changed all length(p^.value_str^) into str_length(p)
  1373. to get it work with and without ansistrings
  1374. * changed sourcefiles field of tmodule to a pointer
  1375. Revision 1.30 1998/09/26 15:03:02 florian
  1376. * small problems with DOM and excpetions fixed (code generation
  1377. of raise was wrong and self was sometimes destroyed :()
  1378. Revision 1.29 1998/09/25 00:04:00 florian
  1379. * problems when calling class methods fixed
  1380. Revision 1.28 1998/09/24 14:27:37 peter
  1381. * some better support for openarray
  1382. Revision 1.27 1998/09/24 09:02:13 peter
  1383. * rewritten isconvertable to use case
  1384. * array of .. and single variable are compatible
  1385. Revision 1.26 1998/09/21 08:45:06 pierre
  1386. + added vmt_offset in tobjectdef.write for fututre use
  1387. (first steps to have objects without vmt if no virtual !!)
  1388. + added fpu_used field for tabstractprocdef :
  1389. sets this level to 2 if the functions return with value in FPU
  1390. (is then set to correct value at parsing of implementation)
  1391. THIS MIGHT refuse some code with FPU expression too complex
  1392. that were accepted before and even in some cases
  1393. that don't overflow in fact
  1394. ( like if f : float; is a forward that finally in implementation
  1395. only uses one fpu register !!)
  1396. Nevertheless I think that it will improve security on
  1397. FPU operations !!
  1398. * most other changes only for UseBrowser code
  1399. (added symtable references for record and objects)
  1400. local switch for refs to args and local of each function
  1401. (static symtable still missing)
  1402. UseBrowser still not stable and probably broken by
  1403. the definition hash array !!
  1404. Revision 1.25 1998/09/20 12:26:35 peter
  1405. * merged fixes
  1406. Revision 1.24 1998/09/17 09:42:10 peter
  1407. + pass_2 for cg386
  1408. * Message() -> CGMessage() for pass_1/pass_2
  1409. Revision 1.23 1998/09/14 10:43:45 peter
  1410. * all internal RTL functions start with FPC_
  1411. Revision 1.22.2.1 1998/09/20 12:20:06 peter
  1412. * Fixed stack not on 4 byte boundary when doing a call
  1413. Revision 1.22 1998/09/04 08:41:37 peter
  1414. * updated some error CGMessages
  1415. Revision 1.21 1998/09/01 12:47:57 peter
  1416. * use pdef^.size instead of orddef^.typ
  1417. Revision 1.20 1998/08/31 12:22:15 peter
  1418. * secondinline moved to cg386inl
  1419. Revision 1.19 1998/08/31 08:52:03 peter
  1420. * fixed error 10 with succ() and pref()
  1421. Revision 1.18 1998/08/20 21:36:38 peter
  1422. * fixed 'with object do' bug
  1423. Revision 1.17 1998/08/19 16:07:36 jonas
  1424. * changed optimizer switches + cleanup of DestroyRefs in daopt386.pas
  1425. Revision 1.16 1998/08/18 09:24:36 pierre
  1426. * small warning position bug fixed
  1427. * support_mmx switches splitting was missing
  1428. * rhide error and warning output corrected
  1429. Revision 1.15 1998/08/13 11:00:09 peter
  1430. * fixed procedure<>procedure construct
  1431. Revision 1.14 1998/08/11 14:05:33 peter
  1432. * fixed sizeof(array of char)
  1433. Revision 1.13 1998/08/10 14:49:45 peter
  1434. + localswitches, moduleswitches, globalswitches splitting
  1435. Revision 1.12 1998/07/30 13:30:31 florian
  1436. * final implemenation of exception support, maybe it needs
  1437. some fixes :)
  1438. Revision 1.11 1998/07/24 22:16:52 florian
  1439. * internal error 10 together with array access fixed. I hope
  1440. that's the final fix.
  1441. Revision 1.10 1998/07/18 22:54:23 florian
  1442. * some ansi/wide/longstring support fixed:
  1443. o parameter passing
  1444. o returning as result from functions
  1445. Revision 1.9 1998/07/07 17:40:37 peter
  1446. * packrecords 4 works
  1447. * word aligning of parameters
  1448. Revision 1.8 1998/07/06 15:51:15 michael
  1449. Added length checking for string reading
  1450. Revision 1.7 1998/07/06 14:19:51 michael
  1451. + Added calls for reading/writing ansistrings
  1452. Revision 1.6 1998/07/01 15:28:48 peter
  1453. + better writeln/readln handling, now 100% like tp7
  1454. Revision 1.5 1998/06/25 14:04:17 peter
  1455. + internal inc/dec
  1456. Revision 1.4 1998/06/25 08:48:06 florian
  1457. * first version of rtti support
  1458. Revision 1.3 1998/06/09 16:01:33 pierre
  1459. + added procedure directive parsing for procvars
  1460. (accepted are popstack cdecl and pascal)
  1461. + added C vars with the following syntax
  1462. var C calias 'true_c_name';(can be followed by external)
  1463. reason is that you must add the Cprefix
  1464. which is target dependent
  1465. Revision 1.2 1998/06/08 13:13:29 pierre
  1466. + temporary variables now in temp_gen.pas unit
  1467. because it is processor independent
  1468. * mppc68k.bat modified to undefine i386 and support_mmx
  1469. (which are defaults for i386)
  1470. Revision 1.1 1998/06/05 17:44:10 peter
  1471. * splitted cgi386
  1472. }