cg386cal.pas 82 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807
  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. uses
  21. symtable,tree;
  22. { save the size of pushed parameter }
  23. var
  24. pushedparasize : longint;
  25. procedure secondcallparan(var p : ptree;defcoll : pdefcoll;
  26. push_from_left_to_right,inlined : boolean;para_offset : longint);
  27. procedure secondcalln(var p : ptree);
  28. procedure secondprocinline(var p : ptree);
  29. implementation
  30. uses
  31. cobjects,verbose,globals,systems,
  32. aasm,types,
  33. {$ifdef GDB}
  34. gdb,
  35. {$endif GDB}
  36. hcodegen,temp_gen,pass_2,
  37. i386,cgai386,tgeni386,cg386ld;
  38. {*****************************************************************************
  39. SecondCallParaN
  40. *****************************************************************************}
  41. procedure secondcallparan(var p : ptree;defcoll : pdefcoll;
  42. push_from_left_to_right,inlined : boolean;para_offset : longint);
  43. function push_addr(p:ptree):boolean;
  44. begin
  45. push_addr:=(
  46. {$ifndef VALUEPARA}
  47. dont_copy_const_param(p^.resulttype) or
  48. {$else}
  49. push_addr_param(p^.resulttype) or
  50. {$endif}
  51. ((p^.treetype=stringconstn) and is_ansistring(p^.resulttype))
  52. );
  53. end;
  54. procedure maybe_push_high;
  55. var
  56. r : preference;
  57. hreg : tregister;
  58. href : treference;
  59. len : longint;
  60. begin
  61. { open array ? }
  62. { defcoll^.data can be nil for read/write }
  63. if assigned(defcoll^.data) and
  64. (is_open_array(defcoll^.data) or
  65. is_open_string(defcoll^.data)) then
  66. begin
  67. { push high }
  68. case p^.left^.resulttype^.deftype of
  69. arraydef : begin
  70. if is_open_array(p^.left^.resulttype) then
  71. begin
  72. r:=new_reference(highframepointer,highoffset+4);
  73. len:=-1;
  74. end
  75. else
  76. len:=parraydef(p^.left^.resulttype)^.highrange-
  77. parraydef(p^.left^.resulttype)^.lowrange
  78. end;
  79. stringdef : begin
  80. if is_open_string(defcoll^.data) then
  81. begin
  82. if is_open_string(p^.left^.resulttype) then
  83. begin
  84. r:=new_reference(highframepointer,highoffset+4);
  85. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,r,R_EDI)));
  86. hreg:=R_EDI;
  87. len:=-2;
  88. end
  89. else
  90. len:=pstringdef(p^.left^.resulttype)^.len
  91. end
  92. else
  93. { passing a string to an array of char }
  94. begin
  95. if (p^.left^.treetype=stringconstn) then
  96. len:=str_length(p^.left)
  97. else
  98. begin
  99. href:=p^.left^.location.reference;
  100. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOVZX,S_BL,newreference(href),R_EDI)));
  101. hreg:=R_EDI;
  102. len:=-2;
  103. end;
  104. end;
  105. end;
  106. else
  107. len:=0;
  108. end;
  109. { Push from the reference? }
  110. if len=-1 then
  111. begin
  112. if inlined then
  113. begin
  114. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,r,R_EDI)));
  115. r:=new_reference(procinfo.framepointer,para_offset-pushedparasize);
  116. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,S_L,R_EDI,r)));
  117. end
  118. else
  119. exprasmlist^.concat(new(pai386,op_ref(A_PUSH,S_L,r)));
  120. end
  121. else
  122. { Push from a register? }
  123. if len=-2 then
  124. begin
  125. if inlined then
  126. begin
  127. r:=new_reference(procinfo.framepointer,para_offset-pushedparasize);
  128. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,S_L,hreg,r)));
  129. end
  130. else
  131. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,hreg)));
  132. ungetregister32(hreg);
  133. end
  134. else
  135. { Push direct value }
  136. begin
  137. if inlined then
  138. begin
  139. r:=new_reference(procinfo.framepointer,para_offset-pushedparasize);
  140. exprasmlist^.concat(new(pai386,op_const_ref(A_MOV,S_L,len,r)));
  141. end
  142. else
  143. push_int(len);
  144. end;
  145. inc(pushedparasize,4);
  146. end;
  147. end;
  148. var
  149. size : longint;
  150. {$ifndef VALUEPARA}
  151. stackref : treference;
  152. {$endif}
  153. otlabel,hlabel,oflabel : plabel;
  154. { temporary variables: }
  155. tempdeftype : tdeftype;
  156. tempreference : treference;
  157. r : preference;
  158. opsize : topsize;
  159. op : tasmop;
  160. hreg : tregister;
  161. begin
  162. { push from left to right if specified }
  163. if push_from_left_to_right and assigned(p^.right) then
  164. secondcallparan(p^.right,defcoll^.next,push_from_left_to_right,inlined,para_offset);
  165. otlabel:=truelabel;
  166. oflabel:=falselabel;
  167. getlabel(truelabel);
  168. getlabel(falselabel);
  169. secondpass(p^.left);
  170. { filter array constructor with c styled args }
  171. if is_array_constructor(p^.left^.resulttype) and p^.left^.cargs then
  172. begin
  173. { nothing, everything is already pushed }
  174. end
  175. { in codegen.handleread.. defcoll^.data is set to nil }
  176. else if assigned(defcoll^.data) and
  177. (defcoll^.data^.deftype=formaldef) then
  178. begin
  179. { allow @var }
  180. inc(pushedparasize,4);
  181. if p^.left^.treetype=addrn then
  182. begin
  183. { always a register }
  184. if inlined then
  185. begin
  186. r:=new_reference(procinfo.framepointer,para_offset-pushedparasize);
  187. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,S_L,
  188. p^.left^.location.register,r)));
  189. end
  190. else
  191. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,p^.left^.location.register)));
  192. ungetregister32(p^.left^.location.register);
  193. end
  194. else
  195. begin
  196. if not(p^.left^.location.loc in [LOC_MEM,LOC_REFERENCE]) then
  197. CGMessage(type_e_mismatch)
  198. else
  199. begin
  200. if inlined then
  201. begin
  202. exprasmlist^.concat(new(pai386,op_ref_reg(A_LEA,S_L,
  203. newreference(p^.left^.location.reference),R_EDI)));
  204. r:=new_reference(procinfo.framepointer,para_offset-pushedparasize);
  205. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,S_L,R_EDI,r)));
  206. end
  207. else
  208. emitpushreferenceaddr(exprasmlist,p^.left^.location.reference);
  209. del_reference(p^.left^.location.reference);
  210. end;
  211. end;
  212. end
  213. { handle call by reference parameter }
  214. else if (defcoll^.paratyp=vs_var) then
  215. begin
  216. if (p^.left^.location.loc<>LOC_REFERENCE) then
  217. CGMessage(cg_e_var_must_be_reference);
  218. maybe_push_high;
  219. inc(pushedparasize,4);
  220. if inlined then
  221. begin
  222. exprasmlist^.concat(new(pai386,op_ref_reg(A_LEA,S_L,
  223. newreference(p^.left^.location.reference),R_EDI)));
  224. r:=new_reference(procinfo.framepointer,para_offset-pushedparasize);
  225. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,S_L,R_EDI,r)));
  226. end
  227. else
  228. emitpushreferenceaddr(exprasmlist,p^.left^.location.reference);
  229. del_reference(p^.left^.location.reference);
  230. end
  231. else
  232. begin
  233. tempdeftype:=p^.resulttype^.deftype;
  234. if tempdeftype=filedef then
  235. CGMessage(cg_e_file_must_call_by_reference);
  236. if
  237. {$ifndef VALUEPARA}
  238. (defcoll^.paratyp=vs_const) and
  239. {$endif}
  240. push_addr(p^.left) then
  241. begin
  242. maybe_push_high;
  243. inc(pushedparasize,4);
  244. if inlined then
  245. begin
  246. exprasmlist^.concat(new(pai386,op_ref_reg(A_LEA,S_L,
  247. newreference(p^.left^.location.reference),R_EDI)));
  248. r:=new_reference(procinfo.framepointer,para_offset-pushedparasize);
  249. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,S_L,
  250. R_EDI,r)));
  251. end
  252. else
  253. emitpushreferenceaddr(exprasmlist,p^.left^.location.reference);
  254. del_reference(p^.left^.location.reference);
  255. end
  256. else
  257. case p^.left^.location.loc of
  258. LOC_REGISTER,
  259. LOC_CREGISTER:
  260. begin
  261. case p^.left^.location.register of
  262. R_EAX,R_EBX,R_ECX,R_EDX,R_ESI,
  263. R_EDI,R_ESP,R_EBP :
  264. begin
  265. inc(pushedparasize,4);
  266. if inlined then
  267. begin
  268. r:=new_reference(procinfo.framepointer,para_offset-pushedparasize);
  269. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,S_L,
  270. p^.left^.location.register,r)));
  271. end
  272. else
  273. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,p^.left^.location.register)));
  274. ungetregister32(p^.left^.location.register);
  275. end;
  276. R_AX,R_BX,R_CX,R_DX,R_SI,R_DI:
  277. begin
  278. if target_os.stackalignment=4 then
  279. begin
  280. opsize:=S_L;
  281. hreg:=reg16toreg32(p^.left^.location.register);
  282. inc(pushedparasize,4);
  283. end
  284. else
  285. begin
  286. opsize:=S_W;
  287. hreg:=p^.left^.location.register;
  288. inc(pushedparasize,2);
  289. end;
  290. if inlined then
  291. begin
  292. r:=new_reference(procinfo.framepointer,para_offset-pushedparasize);
  293. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,opsize,hreg,r)));
  294. end
  295. else
  296. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,opsize,hreg)));
  297. ungetregister32(reg16toreg32(p^.left^.location.register));
  298. end;
  299. R_AL,R_BL,R_CL,R_DL:
  300. begin
  301. if target_os.stackalignment=4 then
  302. begin
  303. opsize:=S_L;
  304. hreg:=reg8toreg32(p^.left^.location.register);
  305. inc(pushedparasize,4);
  306. end
  307. else
  308. begin
  309. opsize:=S_W;
  310. hreg:=reg8toreg16(p^.left^.location.register);
  311. inc(pushedparasize,2);
  312. end;
  313. { we must push always 16 bit }
  314. if inlined then
  315. begin
  316. r:=new_reference(procinfo.framepointer,para_offset-pushedparasize);
  317. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,opsize,hreg,r)));
  318. end
  319. else
  320. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,opsize,hreg)));
  321. ungetregister32(reg8toreg32(p^.left^.location.register));
  322. end;
  323. end;
  324. end;
  325. LOC_FPU:
  326. begin
  327. size:=align(pfloatdef(p^.left^.resulttype)^.size,target_os.stackalignment);
  328. inc(pushedparasize,size);
  329. if not inlined then
  330. exprasmlist^.concat(new(pai386,op_const_reg(A_SUB,S_L,size,R_ESP)));
  331. {$ifdef GDB}
  332. if (cs_debuginfo in aktmoduleswitches) and
  333. (exprasmlist^.first=exprasmlist^.last) then
  334. exprasmlist^.concat(new(pai_force_line,init));
  335. {$endif GDB}
  336. r:=new_reference(R_ESP,0);
  337. floatstoreops(pfloatdef(p^.left^.resulttype)^.typ,op,opsize);
  338. { this is the easiest case for inlined !! }
  339. if inlined then
  340. begin
  341. r^.base:=procinfo.framepointer;
  342. r^.offset:=para_offset-pushedparasize;
  343. end;
  344. exprasmlist^.concat(new(pai386,op_ref(op,opsize,r)));
  345. end;
  346. LOC_REFERENCE,LOC_MEM:
  347. begin
  348. tempreference:=p^.left^.location.reference;
  349. del_reference(p^.left^.location.reference);
  350. case p^.resulttype^.deftype of
  351. enumdef,
  352. orddef :
  353. begin
  354. case p^.resulttype^.size of
  355. 4 : begin
  356. inc(pushedparasize,4);
  357. if inlined then
  358. begin
  359. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,
  360. newreference(tempreference),R_EDI)));
  361. r:=new_reference(procinfo.framepointer,para_offset-pushedparasize);
  362. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,S_L,R_EDI,r)));
  363. end
  364. else
  365. emit_push_mem(tempreference);
  366. end;
  367. 1,2 : begin
  368. if target_os.stackalignment=4 then
  369. begin
  370. opsize:=S_L;
  371. hreg:=R_EDI;
  372. inc(pushedparasize,4);
  373. end
  374. else
  375. begin
  376. opsize:=S_W;
  377. hreg:=R_DI;
  378. inc(pushedparasize,2);
  379. end;
  380. if inlined then
  381. begin
  382. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,opsize,
  383. newreference(tempreference),hreg)));
  384. r:=new_reference(procinfo.framepointer,para_offset-pushedparasize);
  385. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,opsize,hreg,r)));
  386. end
  387. else
  388. exprasmlist^.concat(new(pai386,op_ref(A_PUSH,opsize,
  389. newreference(tempreference))));
  390. end;
  391. else
  392. internalerror(234231);
  393. end;
  394. end;
  395. floatdef :
  396. begin
  397. case pfloatdef(p^.resulttype)^.typ of
  398. f32bit,
  399. s32real :
  400. begin
  401. inc(pushedparasize,4);
  402. if inlined then
  403. begin
  404. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,
  405. newreference(tempreference),R_EDI)));
  406. r:=new_reference(procinfo.framepointer,para_offset-pushedparasize);
  407. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,S_L,R_EDI,r)));
  408. end
  409. else
  410. emit_push_mem(tempreference);
  411. end;
  412. s64real,
  413. s64bit :
  414. begin
  415. inc(pushedparasize,4);
  416. inc(tempreference.offset,4);
  417. if inlined then
  418. begin
  419. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,
  420. newreference(tempreference),R_EDI)));
  421. r:=new_reference(procinfo.framepointer,para_offset-pushedparasize);
  422. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,S_L,R_EDI,r)));
  423. end
  424. else
  425. emit_push_mem(tempreference);
  426. inc(pushedparasize,4);
  427. dec(tempreference.offset,4);
  428. if inlined then
  429. begin
  430. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,
  431. newreference(tempreference),R_EDI)));
  432. r:=new_reference(procinfo.framepointer,para_offset-pushedparasize);
  433. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,S_L,R_EDI,r)));
  434. end
  435. else
  436. emit_push_mem(tempreference);
  437. end;
  438. s80real :
  439. begin
  440. inc(pushedparasize,4);
  441. if target_os.stackalignment=4 then
  442. inc(tempreference.offset,8)
  443. else
  444. inc(tempreference.offset,6);
  445. if inlined then
  446. begin
  447. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,
  448. newreference(tempreference),R_EDI)));
  449. r:=new_reference(procinfo.framepointer,para_offset-pushedparasize);
  450. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,S_L,R_EDI,r)));
  451. end
  452. else
  453. emit_push_mem(tempreference);
  454. dec(tempreference.offset,4);
  455. inc(pushedparasize,4);
  456. if inlined then
  457. begin
  458. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,
  459. newreference(tempreference),R_EDI)));
  460. r:=new_reference(procinfo.framepointer,para_offset-pushedparasize);
  461. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,S_L,R_EDI,r)));
  462. end
  463. else
  464. emit_push_mem(tempreference);
  465. if target_os.stackalignment=4 then
  466. begin
  467. opsize:=S_L;
  468. hreg:=R_EDI;
  469. inc(pushedparasize,4);
  470. dec(tempreference.offset,4);
  471. end
  472. else
  473. begin
  474. opsize:=S_W;
  475. hreg:=R_DI;
  476. inc(pushedparasize,2);
  477. dec(tempreference.offset,2);
  478. end;
  479. if inlined then
  480. begin
  481. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,opsize,
  482. newreference(tempreference),hreg)));
  483. r:=new_reference(procinfo.framepointer,para_offset-pushedparasize);
  484. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,opsize,hreg,r)));
  485. end
  486. else
  487. exprasmlist^.concat(new(pai386,op_ref(A_PUSH,opsize,
  488. newreference(tempreference))));
  489. end;
  490. end;
  491. end;
  492. pointerdef,procvardef,
  493. classrefdef:
  494. begin
  495. inc(pushedparasize,4);
  496. if inlined then
  497. begin
  498. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,
  499. newreference(tempreference),R_EDI)));
  500. r:=new_reference(procinfo.framepointer,para_offset-pushedparasize);
  501. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,S_L,R_EDI,r)));
  502. end
  503. else
  504. emit_push_mem(tempreference);
  505. end;
  506. arraydef,recorddef,stringdef,setdef,objectdef :
  507. begin
  508. { 32 bit type set ? }
  509. if is_widestring(p^.resulttype) or
  510. is_ansistring(p^.resulttype) or
  511. is_smallset(p^.resulttype) then
  512. begin
  513. inc(pushedparasize,4);
  514. if inlined then
  515. begin
  516. r:=new_reference(procinfo.framepointer,para_offset-pushedparasize);
  517. concatcopy(tempreference,r^,4,false,false);
  518. end
  519. else
  520. emit_push_mem(tempreference);
  521. end
  522. { call by value open array ? }
  523. else
  524. {$ifndef VALUEPARA}
  525. if (p^.resulttype^.deftype=arraydef) and
  526. assigned(defcoll^.data) and
  527. is_open_array(defcoll^.data) then
  528. begin
  529. { first, push high }
  530. maybe_push_high;
  531. inc(pushedparasize,4);
  532. if inlined then
  533. begin
  534. exprasmlist^.concat(new(pai386,op_ref_reg(A_LEA,S_L,
  535. newreference(p^.left^.location.reference),R_EDI)));
  536. r:=new_reference(procinfo.framepointer,para_offset-pushedparasize);
  537. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,S_L,
  538. R_EDI,r)));
  539. end
  540. else
  541. emitpushreferenceaddr(exprasmlist,p^.left^.location.reference);
  542. end
  543. else
  544. begin
  545. size:=align(p^.resulttype^.size,target_os.stackalignment);
  546. { create stack space }
  547. if not inlined then
  548. exprasmlist^.concat(new(pai386,op_const_reg(A_SUB,S_L,size,R_ESP)));
  549. {$ifdef GDB}
  550. if (cs_debuginfo in aktmoduleswitches) and
  551. (exprasmlist^.first=exprasmlist^.last) then
  552. exprasmlist^.concat(new(pai_force_line,init));
  553. {$endif GDB}
  554. inc(pushedparasize,size);
  555. { create stack reference }
  556. stackref.symbol := nil;
  557. if not inlined then
  558. begin
  559. clear_reference(stackref);
  560. stackref.base:=R_ESP;
  561. end
  562. else
  563. begin
  564. clear_reference(stackref);
  565. stackref.base:=procinfo.framepointer;
  566. stackref.offset:=para_offset-pushedparasize;
  567. end;
  568. { generate copy }
  569. if is_shortstring(p^.resulttype) then
  570. begin
  571. copyshortstring(stackref,p^.left^.location.reference,
  572. pstringdef(p^.resulttype)^.len,false);
  573. end
  574. else
  575. begin
  576. concatcopy(p^.left^.location.reference,
  577. stackref,p^.resulttype^.size,true,false);
  578. end;
  579. end;
  580. {$else VALUEPARA}
  581. begin
  582. internalerror(8954);
  583. end;
  584. {$endif VALUEPARA}
  585. end;
  586. else
  587. CGMessage(cg_e_illegal_expression);
  588. end;
  589. end;
  590. LOC_JUMP:
  591. begin
  592. getlabel(hlabel);
  593. if target_os.stackalignment=4 then
  594. begin
  595. opsize:=S_L;
  596. inc(pushedparasize,4);
  597. end
  598. else
  599. begin
  600. opsize:=S_W;
  601. inc(pushedparasize,2);
  602. end;
  603. emitl(A_LABEL,truelabel);
  604. if inlined then
  605. begin
  606. r:=new_reference(procinfo.framepointer,para_offset-pushedparasize);
  607. exprasmlist^.concat(new(pai386,op_const_ref(A_MOV,opsize,1,r)));
  608. end
  609. else
  610. exprasmlist^.concat(new(pai386,op_const(A_PUSH,opsize,1)));
  611. emitl(A_JMP,hlabel);
  612. emitl(A_LABEL,falselabel);
  613. if inlined then
  614. begin
  615. r:=new_reference(procinfo.framepointer,para_offset-pushedparasize);
  616. exprasmlist^.concat(new(pai386,op_const_ref(A_MOV,opsize,0,r)));
  617. end
  618. else
  619. exprasmlist^.concat(new(pai386,op_const(A_PUSH,opsize,0)));
  620. emitl(A_LABEL,hlabel);
  621. end;
  622. LOC_FLAGS:
  623. begin
  624. if not(R_EAX in unused) then
  625. exprasmlist^.concat(new(pai386,op_reg_reg(A_MOV,S_L,R_EAX,R_EDI)));
  626. exprasmlist^.concat(new(pai386,op_reg(flag_2_set[p^.left^.location.resflags],S_B,
  627. R_AL)));
  628. exprasmlist^.concat(new(pai386,op_reg_reg(A_MOVZX,S_BW,R_AL,R_AX)));
  629. if target_os.stackalignment=4 then
  630. begin
  631. opsize:=S_L;
  632. hreg:=R_EAX;
  633. inc(pushedparasize,4);
  634. end
  635. else
  636. begin
  637. opsize:=S_W;
  638. hreg:=R_AX;
  639. inc(pushedparasize,2);
  640. end;
  641. if inlined then
  642. begin
  643. r:=new_reference(procinfo.framepointer,para_offset-pushedparasize);
  644. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,opsize,hreg,r)));
  645. end
  646. else
  647. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,opsize,hreg)));
  648. if not(R_EAX in unused) then
  649. exprasmlist^.concat(new(pai386,op_reg_reg(A_MOV,S_L,R_EDI,R_EAX)));
  650. end;
  651. {$ifdef SUPPORT_MMX}
  652. LOC_MMXREGISTER,
  653. LOC_CMMXREGISTER:
  654. begin
  655. inc(pushedparasize,8); { was missing !!! (PM) }
  656. exprasmlist^.concat(new(pai386,op_const_reg(
  657. A_SUB,S_L,8,R_ESP)));
  658. {$ifdef GDB}
  659. if (cs_debuginfo in aktmoduleswitches) and
  660. (exprasmlist^.first=exprasmlist^.last) then
  661. exprasmlist^.concat(new(pai_force_line,init));
  662. {$endif GDB}
  663. if inlined then
  664. begin
  665. r:=new_reference(procinfo.framepointer,para_offset-pushedparasize);
  666. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOVQ,S_NO,
  667. p^.left^.location.register,r)));
  668. end
  669. else
  670. begin
  671. r:=new_reference(R_ESP,0);
  672. exprasmlist^.concat(new(pai386,op_reg_ref(
  673. A_MOVQ,S_NO,p^.left^.location.register,r)));
  674. end;
  675. end;
  676. {$endif SUPPORT_MMX}
  677. end;
  678. end;
  679. freelabel(truelabel);
  680. freelabel(falselabel);
  681. truelabel:=otlabel;
  682. falselabel:=oflabel;
  683. { push from right to left }
  684. if not push_from_left_to_right and assigned(p^.right) then
  685. secondcallparan(p^.right,defcoll^.next,push_from_left_to_right,inlined,para_offset);
  686. end;
  687. {*****************************************************************************
  688. SecondCallN
  689. *****************************************************************************}
  690. procedure secondcalln(var p : ptree);
  691. var
  692. unusedregisters : tregisterset;
  693. pushed : tpushed;
  694. hr,funcretref : treference;
  695. hregister : tregister;
  696. oldpushedparasize : longint;
  697. { true if ESI must be loaded again after the subroutine }
  698. loadesi : boolean;
  699. { true if a virtual method must be called directly }
  700. no_virtual_call : boolean;
  701. { true if we produce a con- or destrutor in a call }
  702. is_con_or_destructor : boolean;
  703. { true if a constructor is called again }
  704. extended_new : boolean;
  705. { adress returned from an I/O-error }
  706. iolabel : plabel;
  707. { lexlevel count }
  708. i : longint;
  709. { help reference pointer }
  710. r : preference;
  711. hp,
  712. pp,params : ptree;
  713. inlined : boolean;
  714. inlinecode : ptree;
  715. para_offset : longint;
  716. { instruction for alignement correction }
  717. { corr : pai386;}
  718. { we must pop this size also after !! }
  719. { must_pop : boolean; }
  720. pop_size : longint;
  721. label
  722. dont_call;
  723. begin
  724. extended_new:=false;
  725. iolabel:=nil;
  726. inlinecode:=nil;
  727. inlined:=false;
  728. loadesi:=true;
  729. no_virtual_call:=false;
  730. unusedregisters:=unused;
  731. if not assigned(p^.procdefinition) then
  732. exit;
  733. if (p^.procdefinition^.options and poinline)<>0 then
  734. begin
  735. inlined:=true;
  736. inlinecode:=p^.right;
  737. { set it to the same lexical level }
  738. p^.procdefinition^.parast^.symtablelevel:=
  739. aktprocsym^.definition^.parast^.symtablelevel;
  740. if assigned(p^.left) then
  741. inlinecode^.para_offset:=
  742. gettempofsizepersistant(inlinecode^.para_size);
  743. p^.procdefinition^.parast^.call_offset:=
  744. inlinecode^.para_offset;
  745. {$ifdef extdebug}
  746. Comment(V_debug,
  747. 'inlined parasymtable is at offset '
  748. +tostr(p^.procdefinition^.parast^.call_offset));
  749. exprasmlist^.concat(new(pai_asm_comment,init(
  750. strpnew('inlined parasymtable is at offset '
  751. +tostr(p^.procdefinition^.parast^.call_offset)))));
  752. {$endif extdebug}
  753. p^.right:=nil;
  754. { disable further inlining of the same proc
  755. in the args }
  756. p^.procdefinition^.options:=p^.procdefinition^.options and (not poinline);
  757. end;
  758. { only if no proc var }
  759. if not(assigned(p^.right)) then
  760. is_con_or_destructor:=((p^.procdefinition^.options and poconstructor)<>0)
  761. or ((p^.procdefinition^.options and podestructor)<>0);
  762. { proc variables destroy all registers }
  763. if (p^.right=nil) and
  764. { virtual methods too }
  765. ((p^.procdefinition^.options and povirtualmethod)=0) then
  766. begin
  767. if ((p^.procdefinition^.options and poiocheck)<>0) and
  768. ((aktprocsym^.definition^.options and poiocheck)=0) and
  769. (cs_check_io in aktlocalswitches) then
  770. begin
  771. getlabel(iolabel);
  772. emitl(A_LABEL,iolabel);
  773. end
  774. else
  775. iolabel:=nil;
  776. { save all used registers }
  777. pushusedregisters(pushed,p^.procdefinition^.usedregisters);
  778. { give used registers through }
  779. usedinproc:=usedinproc or p^.procdefinition^.usedregisters;
  780. end
  781. else
  782. begin
  783. pushusedregisters(pushed,$ff);
  784. usedinproc:=$ff;
  785. { no IO check for methods and procedure variables }
  786. iolabel:=nil;
  787. end;
  788. { generate the code for the parameter and push them }
  789. oldpushedparasize:=pushedparasize;
  790. pushedparasize:=0;
  791. pop_size:=0;
  792. if (not inlined) then
  793. begin
  794. { Old pushedsize aligned on 4 ? }
  795. i:=oldpushedparasize and 3;
  796. if i>0 then
  797. inc(pop_size,4-i);
  798. { This parasize aligned on 4 ? }
  799. i:=p^.procdefinition^.para_size and 3;
  800. if i>0 then
  801. inc(pop_size,4-i);
  802. { insert the opcode and update pushedparasize }
  803. if pop_size>0 then
  804. begin
  805. inc(pushedparasize,pop_size);
  806. exprasmlist^.concat(new(pai386,op_const_reg(A_SUB,S_L,pop_size,R_ESP)));
  807. {$ifdef GDB}
  808. if (cs_debuginfo in aktmoduleswitches) and
  809. (exprasmlist^.first=exprasmlist^.last) then
  810. exprasmlist^.concat(new(pai_force_line,init));
  811. {$endif GDB}
  812. end;
  813. end;
  814. if (p^.resulttype<>pdef(voiddef)) and
  815. ret_in_param(p^.resulttype) then
  816. begin
  817. funcretref.symbol:=nil;
  818. {$ifdef test_dest_loc}
  819. if dest_loc_known and (dest_loc_tree=p) and
  820. (dest_loc.loc in [LOC_REFERENCE,LOC_MEM]) then
  821. begin
  822. funcretref:=dest_loc.reference;
  823. if assigned(dest_loc.reference.symbol) then
  824. funcretref.symbol:=stringdup(dest_loc.reference.symbol^);
  825. in_dest_loc:=true;
  826. end
  827. else
  828. {$endif test_dest_loc}
  829. if inlined then
  830. begin
  831. reset_reference(funcretref);
  832. funcretref.offset:=gettempofsizepersistant(p^.procdefinition^.retdef^.size);
  833. funcretref.base:=procinfo.framepointer;
  834. end
  835. else
  836. gettempofsizereference(p^.procdefinition^.retdef^.size,funcretref);
  837. end;
  838. if assigned(p^.left) then
  839. begin
  840. { be found elsewhere }
  841. if inlined then
  842. para_offset:=p^.procdefinition^.parast^.call_offset+
  843. p^.procdefinition^.parast^.datasize
  844. else
  845. para_offset:=0;
  846. if assigned(p^.right) then
  847. secondcallparan(p^.left,pprocvardef(p^.right^.resulttype)^.para1,
  848. (p^.procdefinition^.options and poleftright)<>0,inlined,para_offset)
  849. else
  850. secondcallparan(p^.left,p^.procdefinition^.para1,
  851. (p^.procdefinition^.options and poleftright)<>0,inlined,para_offset);
  852. end;
  853. params:=p^.left;
  854. p^.left:=nil;
  855. if inlined then
  856. inlinecode^.retoffset:=gettempofsizepersistant(4);
  857. if ret_in_param(p^.resulttype) then
  858. begin
  859. inc(pushedparasize,4);
  860. if inlined then
  861. begin
  862. exprasmlist^.concat(new(pai386,op_ref_reg(A_LEA,S_L,
  863. newreference(funcretref),R_EDI)));
  864. r:=new_reference(procinfo.framepointer,inlinecode^.retoffset);
  865. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,S_L,
  866. R_EDI,r)));
  867. end
  868. else
  869. emitpushreferenceaddr(exprasmlist,funcretref);
  870. end;
  871. { procedure variable ? }
  872. if (p^.right=nil) then
  873. begin
  874. { overloaded operator have no symtable }
  875. { push self }
  876. if assigned(p^.symtable) and
  877. (p^.symtable^.symtabletype=withsymtable) then
  878. begin
  879. { dirty trick to avoid the secondcall below }
  880. p^.methodpointer:=genzeronode(callparan);
  881. p^.methodpointer^.location.loc:=LOC_REGISTER;
  882. p^.methodpointer^.location.register:=R_ESI;
  883. p^.methodpointer^.resulttype:=p^.symtable^.defowner;
  884. { change dispose type !! }
  885. p^.disposetyp:=dt_mbleft_and_method;
  886. { make a reference }
  887. new(r);
  888. reset_reference(r^);
  889. r^.offset:=p^.symtable^.datasize;
  890. r^.base:=procinfo.framepointer;
  891. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,r,R_ESI)));
  892. end;
  893. { push self }
  894. if assigned(p^.symtable) and
  895. ((p^.symtable^.symtabletype=objectsymtable) or
  896. (p^.symtable^.symtabletype=withsymtable)) then
  897. begin
  898. if assigned(p^.methodpointer) then
  899. begin
  900. {
  901. if p^.methodpointer^.resulttype=classrefdef then
  902. begin
  903. two possibilities:
  904. 1. constructor
  905. 2. class method
  906. end
  907. else }
  908. begin
  909. case p^.methodpointer^.treetype of
  910. typen:
  911. begin
  912. { direct call to inherited method }
  913. if (p^.procdefinition^.options and poabstractmethod)<>0 then
  914. begin
  915. CGMessage(cg_e_cant_call_abstract_method);
  916. goto dont_call;
  917. end;
  918. { generate no virtual call }
  919. no_virtual_call:=true;
  920. if (p^.symtableprocentry^.properties and sp_static)<>0 then
  921. begin
  922. { well lets put the VMT address directly into ESI }
  923. { it is kind of dirty but that is the simplest }
  924. { way to accept virtual static functions (PM) }
  925. loadesi:=true;
  926. exprasmlist^.concat(new(pai386,op_csymbol_reg(A_MOV,S_L,
  927. newcsymbol(pobjectdef(p^.methodpointer^.resulttype)^.vmt_mangledname,0),R_ESI)));
  928. maybe_concat_external(pobjectdef(p^.methodpointer^.resulttype)^.owner,
  929. pobjectdef(p^.methodpointer^.resulttype)^.vmt_mangledname);
  930. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,R_ESI)));
  931. end
  932. else
  933. { this is a member call, so ESI isn't modfied }
  934. loadesi:=false;
  935. if not(is_con_or_destructor and
  936. pobjectdef(p^.methodpointer^.resulttype)^.isclass and
  937. assigned(aktprocsym) and
  938. ((aktprocsym^.definition^.options and
  939. (poconstructor or podestructor))<>0)) then
  940. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,R_ESI)));
  941. { if an inherited con- or destructor should be }
  942. { called in a con- or destructor then a warning }
  943. { will be made }
  944. { con- and destructors need a pointer to the vmt }
  945. if is_con_or_destructor and
  946. not(pobjectdef(p^.methodpointer^.resulttype)^.isclass) and
  947. assigned(aktprocsym) then
  948. begin
  949. if not ((aktprocsym^.definition^.options
  950. and (poconstructor or podestructor))<>0) then
  951. CGMessage(cg_w_member_cd_call_from_method);
  952. end;
  953. if is_con_or_destructor then
  954. push_int(0)
  955. end;
  956. hnewn:
  957. begin
  958. { extended syntax of new }
  959. { ESI must be zero }
  960. exprasmlist^.concat(new(pai386,op_reg_reg(A_XOR,S_L,R_ESI,R_ESI)));
  961. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,R_ESI)));
  962. { insert the vmt }
  963. exprasmlist^.concat(new(pai386,op_csymbol(A_PUSH,S_L,
  964. newcsymbol(pobjectdef(p^.methodpointer^.resulttype)^.vmt_mangledname,0))));
  965. maybe_concat_external(pobjectdef(p^.methodpointer^.resulttype)^.owner,
  966. pobjectdef(p^.methodpointer^.resulttype)^.vmt_mangledname);
  967. extended_new:=true;
  968. end;
  969. hdisposen:
  970. begin
  971. secondpass(p^.methodpointer);
  972. { destructor with extended syntax called from dispose }
  973. { hdisposen always deliver LOC_REFERENCE }
  974. exprasmlist^.concat(new(pai386,op_ref_reg(A_LEA,S_L,
  975. newreference(p^.methodpointer^.location.reference),R_ESI)));
  976. del_reference(p^.methodpointer^.location.reference);
  977. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,R_ESI)));
  978. exprasmlist^.concat(new(pai386,op_csymbol(A_PUSH,S_L,
  979. newcsymbol(pobjectdef(p^.methodpointer^.resulttype)^.vmt_mangledname,0))));
  980. maybe_concat_external(pobjectdef(p^.methodpointer^.resulttype)^.owner,
  981. pobjectdef(p^.methodpointer^.resulttype)^.vmt_mangledname);
  982. end;
  983. else
  984. begin
  985. { call to an instance member }
  986. if (p^.symtable^.symtabletype<>withsymtable) then
  987. begin
  988. secondpass(p^.methodpointer);
  989. case p^.methodpointer^.location.loc of
  990. LOC_CREGISTER,
  991. LOC_REGISTER:
  992. begin
  993. ungetregister32(p^.methodpointer^.location.register);
  994. emit_reg_reg(A_MOV,S_L,p^.methodpointer^.location.register,R_ESI);
  995. end;
  996. else
  997. begin
  998. if (p^.methodpointer^.resulttype^.deftype=classrefdef) or
  999. ((p^.methodpointer^.resulttype^.deftype=objectdef) and
  1000. pobjectdef(p^.methodpointer^.resulttype)^.isclass) then
  1001. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,
  1002. newreference(p^.methodpointer^.location.reference),R_ESI)))
  1003. else
  1004. exprasmlist^.concat(new(pai386,op_ref_reg(A_LEA,S_L,
  1005. newreference(p^.methodpointer^.location.reference),R_ESI)));
  1006. del_reference(p^.methodpointer^.location.reference);
  1007. end;
  1008. end;
  1009. end;
  1010. { when calling a class method, we have
  1011. to load ESI with the VMT !
  1012. But that's wrong, if we call a class method via self
  1013. }
  1014. if ((p^.procdefinition^.options and poclassmethod)<>0)
  1015. and not(p^.methodpointer^.resulttype^.deftype=classrefdef) then
  1016. begin
  1017. { class method needs current VMT }
  1018. new(r);
  1019. reset_reference(r^);
  1020. r^.base:=R_ESI;
  1021. r^.offset:= p^.procdefinition^._class^.vmt_offset;
  1022. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,r,R_ESI)));
  1023. end;
  1024. { direct call to class constructor, don't allocate memory }
  1025. if is_con_or_destructor and
  1026. (p^.methodpointer^.resulttype^.deftype=objectdef) and
  1027. (pobjectdef(p^.methodpointer^.resulttype)^.isclass) then
  1028. exprasmlist^.concat(new(pai386,op_const(A_PUSH,S_L,0)))
  1029. else
  1030. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,R_ESI)));
  1031. if is_con_or_destructor then
  1032. begin
  1033. { classes don't get a VMT pointer pushed }
  1034. if (p^.methodpointer^.resulttype^.deftype=objectdef) and
  1035. not(pobjectdef(p^.methodpointer^.resulttype)^.isclass) then
  1036. begin
  1037. if ((p^.procdefinition^.options and poconstructor)<>0) then
  1038. begin
  1039. { it's no bad idea, to insert the VMT }
  1040. exprasmlist^.concat(new(pai386,op_csymbol(A_PUSH,S_L,
  1041. newcsymbol(pobjectdef(p^.methodpointer^.resulttype)^.vmt_mangledname,
  1042. 0))));
  1043. maybe_concat_external(pobjectdef(p^.methodpointer^.resulttype)^.owner,
  1044. pobjectdef(p^.methodpointer^.resulttype)^.vmt_mangledname);
  1045. end
  1046. { destructors haven't to dispose the instance, if this is }
  1047. { a direct call }
  1048. else
  1049. push_int(0);
  1050. end;
  1051. end;
  1052. end;
  1053. end;
  1054. end;
  1055. end
  1056. else
  1057. begin
  1058. if ((p^.procdefinition^.options and poclassmethod)<>0) and
  1059. not(
  1060. assigned(aktprocsym) and
  1061. ((aktprocsym^.definition^.options and poclassmethod)<>0)
  1062. ) then
  1063. begin
  1064. { class method needs current VMT }
  1065. new(r);
  1066. reset_reference(r^);
  1067. r^.base:=R_ESI;
  1068. r^.offset:= p^.procdefinition^._class^.vmt_offset;
  1069. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,r,R_ESI)));
  1070. end
  1071. else
  1072. begin
  1073. { member call, ESI isn't modified }
  1074. loadesi:=false;
  1075. end;
  1076. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,R_ESI)));
  1077. { but a con- or destructor here would probably almost }
  1078. { always be placed wrong }
  1079. if is_con_or_destructor then
  1080. begin
  1081. CGMessage(cg_w_member_cd_call_from_method);
  1082. push_int(0);
  1083. end;
  1084. end;
  1085. end;
  1086. { push base pointer ?}
  1087. if (lexlevel>=normal_function_level) and assigned(pprocdef(p^.procdefinition)^.parast) and
  1088. ((p^.procdefinition^.parast^.symtablelevel)>normal_function_level) then
  1089. begin
  1090. { if we call a nested function in a method, we must }
  1091. { push also SELF! }
  1092. { THAT'S NOT TRUE, we have to load ESI via frame pointer }
  1093. { access }
  1094. {
  1095. begin
  1096. loadesi:=false;
  1097. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,R_ESI)));
  1098. end;
  1099. }
  1100. if lexlevel=(p^.procdefinition^.parast^.symtablelevel) then
  1101. begin
  1102. new(r);
  1103. reset_reference(r^);
  1104. r^.offset:=procinfo.framepointer_offset;
  1105. r^.base:=procinfo.framepointer;
  1106. exprasmlist^.concat(new(pai386,op_ref(A_PUSH,S_L,r)))
  1107. end
  1108. { this is only true if the difference is one !!
  1109. but it cannot be more !! }
  1110. else if (lexlevel=p^.procdefinition^.parast^.symtablelevel-1) then
  1111. begin
  1112. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,procinfo.framepointer)))
  1113. end
  1114. else if (lexlevel>p^.procdefinition^.parast^.symtablelevel) then
  1115. begin
  1116. hregister:=getregister32;
  1117. new(r);
  1118. reset_reference(r^);
  1119. r^.offset:=procinfo.framepointer_offset;
  1120. r^.base:=procinfo.framepointer;
  1121. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,r,hregister)));
  1122. for i:=(p^.procdefinition^.parast^.symtablelevel) to lexlevel-1 do
  1123. begin
  1124. new(r);
  1125. reset_reference(r^);
  1126. {we should get the correct frame_pointer_offset at each level
  1127. how can we do this !!! }
  1128. r^.offset:=procinfo.framepointer_offset;
  1129. r^.base:=hregister;
  1130. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,r,hregister)));
  1131. end;
  1132. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,hregister)));
  1133. ungetregister32(hregister);
  1134. end
  1135. else
  1136. internalerror(25000);
  1137. end;
  1138. if ((p^.procdefinition^.options and povirtualmethod)<>0) and
  1139. not(no_virtual_call) then
  1140. begin
  1141. { static functions contain the vmt_address in ESI }
  1142. { also class methods }
  1143. if assigned(aktprocsym) then
  1144. begin
  1145. if ((aktprocsym^.properties and sp_static)<>0) or
  1146. ((aktprocsym^.definition^.options and poclassmethod)<>0) or
  1147. ((p^.procdefinition^.options and postaticmethod)<>0) or
  1148. ((p^.procdefinition^.options and poconstructor)<>0) or
  1149. { ESI is loaded earlier }
  1150. ((p^.procdefinition^.options and poclassmethod)<>0)then
  1151. begin
  1152. new(r);
  1153. reset_reference(r^);
  1154. r^.base:=R_ESI;
  1155. end
  1156. else
  1157. begin
  1158. new(r);
  1159. reset_reference(r^);
  1160. r^.base:=R_ESI;
  1161. { this is one point where we need vmt_offset (PM) }
  1162. r^.offset:= p^.procdefinition^._class^.vmt_offset;
  1163. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,r,R_EDI)));
  1164. new(r);
  1165. reset_reference(r^);
  1166. r^.base:=R_EDI;
  1167. end;
  1168. end
  1169. else
  1170. { aktprocsym should be assigned, also in main program }
  1171. internalerror(12345);
  1172. {
  1173. begin
  1174. new(r);
  1175. reset_reference(r^);
  1176. r^.base:=R_ESI;
  1177. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,r,R_EDI)));
  1178. new(r);
  1179. reset_reference(r^);
  1180. r^.base:=R_EDI;
  1181. end;
  1182. }
  1183. if p^.procdefinition^.extnumber=-1 then
  1184. internalerror($Da);
  1185. r^.offset:=p^.procdefinition^.extnumber*4+12;
  1186. if (cs_check_range in aktlocalswitches) then
  1187. begin
  1188. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,r^.base)));
  1189. emitcall('FPC_CHECK_OBJECT',true);
  1190. end;
  1191. exprasmlist^.concat(new(pai386,op_ref(A_CALL,S_NO,r)));
  1192. end
  1193. else if not inlined then
  1194. emitcall(p^.procdefinition^.mangledname,
  1195. (p^.symtableproc^.symtabletype=unitsymtable) or
  1196. ((p^.symtableproc^.symtabletype=objectsymtable) and
  1197. (pobjectdef(p^.symtableproc^.defowner)^.owner^.symtabletype=unitsymtable))or
  1198. ((p^.symtableproc^.symtabletype=withsymtable) and
  1199. (pobjectdef(p^.symtableproc^.defowner)^.owner^.symtabletype=unitsymtable)))
  1200. else { inlined proc }
  1201. { inlined code is in inlinecode }
  1202. begin
  1203. secondpass(inlinecode);
  1204. { set poinline again }
  1205. p^.procdefinition^.options:=p^.procdefinition^.options or poinline;
  1206. { free the args }
  1207. ungetpersistanttemp(p^.procdefinition^.parast^.call_offset,
  1208. p^.procdefinition^.parast^.datasize);
  1209. end;
  1210. end
  1211. else
  1212. { now procedure variable case }
  1213. begin
  1214. secondpass(p^.right);
  1215. { method pointer ? }
  1216. if (p^.procdefinition^.options and pomethodpointer)<>0 then
  1217. begin
  1218. { method pointer can't be in a register }
  1219. inc(p^.right^.location.reference.offset,4);
  1220. { push self pointer }
  1221. exprasmlist^.concat(new(pai386,op_ref(A_PUSH,S_L,newreference(p^.right^.location.reference))));
  1222. del_reference(p^.right^.location.reference);
  1223. dec(p^.right^.location.reference.offset,4);
  1224. end;
  1225. case p^.right^.location.loc of
  1226. LOC_REGISTER,LOC_CREGISTER:
  1227. begin
  1228. exprasmlist^.concat(new(pai386,op_reg(A_CALL,S_NO,p^.right^.location.register)));
  1229. ungetregister32(p^.right^.location.register);
  1230. end
  1231. else
  1232. exprasmlist^.concat(new(pai386,op_ref(A_CALL,S_NO,newreference(p^.right^.location.reference))));
  1233. del_reference(p^.right^.location.reference);
  1234. end;
  1235. end;
  1236. { this was only for normal functions
  1237. displaced here so we also get
  1238. it to work for procvars PM }
  1239. if (not inlined) and ((p^.procdefinition^.options and poclearstack)<>0) then
  1240. begin
  1241. { consider the alignment with the rest (PM) }
  1242. inc(pushedparasize,pop_size);
  1243. pop_size:=0;
  1244. { better than an add on all processors }
  1245. if pushedparasize=4 then
  1246. exprasmlist^.concat(new(pai386,op_reg(A_POP,S_L,R_EDI)))
  1247. { the pentium has two pipes and pop reg is pairable }
  1248. { but the registers must be different! }
  1249. else if (pushedparasize=8) and
  1250. not(cs_littlesize in aktglobalswitches) and
  1251. (aktoptprocessor=ClassP5) and
  1252. (procinfo._class=nil) then
  1253. begin
  1254. exprasmlist^.concat(new(pai386,op_reg(A_POP,S_L,R_EDI)));
  1255. exprasmlist^.concat(new(pai386,op_reg(A_POP,S_L,R_ESI)));
  1256. end
  1257. else exprasmlist^.concat(new(pai386,op_const_reg(A_ADD,S_L,pushedparasize,R_ESP)));
  1258. end;
  1259. dont_call:
  1260. pushedparasize:=oldpushedparasize;
  1261. unused:=unusedregisters;
  1262. { handle function results }
  1263. { structured results are easy to handle.... }
  1264. { needed also when result_no_used !! }
  1265. if (p^.resulttype<>pdef(voiddef)) and ret_in_param(p^.resulttype) then
  1266. begin
  1267. p^.location.loc:=LOC_MEM;
  1268. stringdispose(p^.location.reference.symbol);
  1269. p^.location.reference:=funcretref;
  1270. end;
  1271. if (p^.resulttype<>pdef(voiddef)) and p^.return_value_used then
  1272. begin
  1273. { a contructor could be a function with boolean result }
  1274. if (p^.right=nil) and
  1275. ((p^.procdefinition^.options and poconstructor)<>0) and
  1276. { quick'n'dirty check if it is a class or an object }
  1277. (p^.resulttype^.deftype=orddef) then
  1278. begin
  1279. p^.location.loc:=LOC_FLAGS;
  1280. p^.location.resflags:=F_NE;
  1281. if extended_new then
  1282. begin
  1283. {$ifdef test_dest_loc}
  1284. if dest_loc_known and (dest_loc_tree=p) then
  1285. mov_reg_to_dest(p,S_L,R_EAX)
  1286. else
  1287. {$endif test_dest_loc}
  1288. begin
  1289. hregister:=getexplicitregister32(R_EAX);
  1290. emit_reg_reg(A_MOV,S_L,R_EAX,hregister);
  1291. p^.location.register:=hregister;
  1292. end;
  1293. end;
  1294. end
  1295. { structed results are easy to handle.... }
  1296. else if ret_in_param(p^.resulttype) then
  1297. begin
  1298. {p^.location.loc:=LOC_MEM;
  1299. stringdispose(p^.location.reference.symbol);
  1300. p^.location.reference:=funcretref;
  1301. already done above (PM) }
  1302. end
  1303. else
  1304. begin
  1305. if (p^.resulttype^.deftype=orddef) then
  1306. begin
  1307. p^.location.loc:=LOC_REGISTER;
  1308. case porddef(p^.resulttype)^.typ of
  1309. s32bit,u32bit,bool32bit :
  1310. begin
  1311. {$ifdef test_dest_loc}
  1312. if dest_loc_known and (dest_loc_tree=p) then
  1313. mov_reg_to_dest(p,S_L,R_EAX)
  1314. else
  1315. {$endif test_dest_loc}
  1316. begin
  1317. hregister:=getexplicitregister32(R_EAX);
  1318. emit_reg_reg(A_MOV,S_L,R_EAX,hregister);
  1319. p^.location.register:=hregister;
  1320. end;
  1321. end;
  1322. uchar,u8bit,bool8bit,s8bit:
  1323. begin
  1324. {$ifdef test_dest_loc}
  1325. if dest_loc_known and (dest_loc_tree=p) then
  1326. mov_reg_to_dest(p,S_B,R_AL)
  1327. else
  1328. {$endif test_dest_loc}
  1329. begin
  1330. hregister:=getexplicitregister32(R_EAX);
  1331. emit_reg_reg(A_MOV,S_B,R_AL,reg32toreg8(hregister));
  1332. p^.location.register:=reg32toreg8(hregister);
  1333. end;
  1334. end;
  1335. s16bit,u16bit,bool16bit :
  1336. begin
  1337. {$ifdef test_dest_loc}
  1338. if dest_loc_known and (dest_loc_tree=p) then
  1339. mov_reg_to_dest(p,S_W,R_AX)
  1340. else
  1341. {$endif test_dest_loc}
  1342. begin
  1343. hregister:=getexplicitregister32(R_EAX);
  1344. emit_reg_reg(A_MOV,S_W,R_AX,reg32toreg16(hregister));
  1345. p^.location.register:=reg32toreg16(hregister);
  1346. end;
  1347. end;
  1348. else internalerror(7);
  1349. end
  1350. end
  1351. else if (p^.resulttype^.deftype=floatdef) then
  1352. case pfloatdef(p^.resulttype)^.typ of
  1353. f32bit:
  1354. begin
  1355. p^.location.loc:=LOC_REGISTER;
  1356. {$ifdef test_dest_loc}
  1357. if dest_loc_known and (dest_loc_tree=p) then
  1358. mov_reg_to_dest(p,S_L,R_EAX)
  1359. else
  1360. {$endif test_dest_loc}
  1361. begin
  1362. hregister:=getexplicitregister32(R_EAX);
  1363. emit_reg_reg(A_MOV,S_L,R_EAX,hregister);
  1364. p^.location.register:=hregister;
  1365. end;
  1366. end;
  1367. else
  1368. p^.location.loc:=LOC_FPU;
  1369. end
  1370. else
  1371. begin
  1372. p^.location.loc:=LOC_REGISTER;
  1373. {$ifdef test_dest_loc}
  1374. if dest_loc_known and (dest_loc_tree=p) then
  1375. mov_reg_to_dest(p,S_L,R_EAX)
  1376. else
  1377. {$endif test_dest_loc}
  1378. begin
  1379. hregister:=getexplicitregister32(R_EAX);
  1380. emit_reg_reg(A_MOV,S_L,R_EAX,hregister);
  1381. p^.location.register:=hregister;
  1382. if is_ansistring(p^.resulttype) or
  1383. is_widestring(p^.resulttype) then
  1384. begin
  1385. gettempofsizereference(4,hr);
  1386. temptoremove^.concat(new(ptemptodestroy,init(hr,p^.resulttype)));
  1387. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,S_L,p^.location.register,
  1388. newreference(hr))));
  1389. end;
  1390. end;
  1391. end;
  1392. end;
  1393. end;
  1394. { perhaps i/o check ? }
  1395. if iolabel<>nil then
  1396. begin
  1397. exprasmlist^.concat(new(pai386,op_csymbol(A_PUSH,S_L,newcsymbol(lab2str(iolabel),0))));
  1398. emitcall('FPC_IOCHECK',true);
  1399. end;
  1400. if pop_size>0 then
  1401. exprasmlist^.concat(new(pai386,op_const_reg(A_ADD,S_L,pop_size,R_ESP)));
  1402. { restore registers }
  1403. popusedregisters(pushed);
  1404. { at last, restore instance pointer (SELF) }
  1405. if loadesi then
  1406. maybe_loadesi;
  1407. pp:=params;
  1408. while assigned(pp) do
  1409. begin
  1410. if assigned(pp^.left) then
  1411. begin
  1412. if pp^.left^.location.loc in [LOC_REFERENCE,LOC_MEM] then
  1413. ungetiftemp(pp^.left^.location.reference);
  1414. { process also all nodes of an array of const }
  1415. if pp^.left^.treetype=arrayconstructn then
  1416. begin
  1417. if assigned(pp^.left^.left) then
  1418. begin
  1419. hp:=pp^.left;
  1420. while assigned(hp) do
  1421. begin
  1422. if hp^.left^.location.loc in [LOC_REFERENCE,LOC_MEM] then
  1423. ungetiftemp(hp^.left^.location.reference);
  1424. hp:=hp^.right;
  1425. end;
  1426. end;
  1427. end;
  1428. end;
  1429. pp:=pp^.right;
  1430. end;
  1431. if inlined then
  1432. ungetpersistanttemp(inlinecode^.retoffset,4);
  1433. disposetree(params);
  1434. { from now on the result can be freed normally }
  1435. if inlined and ret_in_param(p^.resulttype) then
  1436. persistanttemptonormal(funcretref.offset);
  1437. { if return value is not used }
  1438. if (not p^.return_value_used) and (p^.resulttype<>pdef(voiddef)) then
  1439. begin
  1440. if p^.location.loc in [LOC_MEM,LOC_REFERENCE] then
  1441. { release unused temp }
  1442. ungetiftemp(p^.location.reference)
  1443. else if p^.location.loc=LOC_FPU then
  1444. { release FPU stack }
  1445. exprasmlist^.concat(new(pai386,op_none(A_FDECSTP,S_NO)));
  1446. end;
  1447. end;
  1448. {*****************************************************************************
  1449. SecondProcInlineN
  1450. *****************************************************************************}
  1451. { implementation not complete yet }
  1452. var
  1453. addr_correction : longint;
  1454. procedure correct_address(p : psym);{$ifndef FPC}far;{$endif}
  1455. begin
  1456. if p^.typ=varsym then
  1457. begin
  1458. inc(pvarsym(p)^.address,addr_correction);
  1459. {$ifdef extdebug}
  1460. Comment(V_debug,pvarsym(p)^.name+' is at offset -'
  1461. +tostr(pvarsym(p)^.address));
  1462. exprasmlist^.concat(new(pai_asm_comment,init(
  1463. strpnew(pvarsym(p)^.name+' is at offset -'
  1464. +tostr(pvarsym(p)^.address)))));
  1465. {$endif extdebug}
  1466. end;
  1467. end;
  1468. procedure secondprocinline(var p : ptree);
  1469. var st : psymtable;
  1470. oldprocsym : pprocsym;
  1471. para_size : longint;
  1472. oldprocinfo : tprocinfo;
  1473. { just dummies for genentrycode }
  1474. nostackframe,make_global : boolean;
  1475. proc_names : tstringcontainer;
  1476. inlineentrycode,inlineexitcode : paasmoutput;
  1477. oldexitlabel,oldexit2label,oldquickexitlabel:Plabel;
  1478. begin
  1479. oldexitlabel:=aktexitlabel;
  1480. oldexit2label:=aktexit2label;
  1481. oldquickexitlabel:=quickexitlabel;
  1482. getlabel(aktexitlabel);
  1483. getlabel(aktexit2label);
  1484. oldprocsym:=aktprocsym;
  1485. oldprocinfo:=procinfo;
  1486. { set the return value }
  1487. procinfo.retdef:=p^.inlineprocdef^.retdef;
  1488. procinfo.retoffset:=p^.retoffset;
  1489. { arg space has been filled by the parent secondcall }
  1490. st:=p^.inlineprocdef^.localst;
  1491. { set it to the same lexical level }
  1492. st^.symtablelevel:=
  1493. oldprocsym^.definition^.localst^.symtablelevel;
  1494. if st^.datasize>0 then
  1495. st^.call_offset:=gettempofsizepersistant(st^.datasize);
  1496. {$ifdef extdebug}
  1497. Comment(V_debug,'local symtable is at offset '
  1498. +tostr(st^.call_offset));
  1499. exprasmlist^.concat(new(pai_asm_comment,init(
  1500. strpnew('local symtable is at offset '
  1501. +tostr(st^.call_offset)))));
  1502. {$endif extdebug}
  1503. addr_correction:=-st^.call_offset-st^.datasize;
  1504. st^.foreach(correct_address);
  1505. {$ifdef extdebug}
  1506. exprasmlist^.concat(new(pai_asm_comment,init('Start of inlined proc')));
  1507. {$endif extdebug}
  1508. { takes care of local data initialization }
  1509. inlineentrycode:=new(paasmoutput,init);
  1510. inlineexitcode:=new(paasmoutput,init);
  1511. proc_names.init;
  1512. para_size:=p^.para_size;
  1513. make_global:=false; { to avoid warning }
  1514. genentrycode(inlineentrycode,proc_names,make_global,0,para_size,nostackframe,true);
  1515. exprasmlist^.concatlist(inlineentrycode);
  1516. secondpass(p^.left);
  1517. genexitcode(inlineexitcode,0,false,true);
  1518. exprasmlist^.concatlist(inlineexitcode);
  1519. {$ifdef extdebug}
  1520. exprasmlist^.concat(new(pai_asm_comment,init('End of inlined proc')));
  1521. {$endif extdebug}
  1522. {we can free the local data now }
  1523. if st^.datasize>0 then
  1524. ungetpersistanttemp(st^.call_offset,st^.datasize);
  1525. { set the real address again }
  1526. addr_correction:=-addr_correction;
  1527. st^.foreach(correct_address);
  1528. aktprocsym:=oldprocsym;
  1529. freelabel(aktexitlabel);
  1530. freelabel(aktexit2label);
  1531. aktexitlabel:=oldexitlabel;
  1532. aktexit2label:=oldexit2label;
  1533. quickexitlabel:=oldquickexitlabel;
  1534. procinfo:=oldprocinfo;
  1535. end;
  1536. end.
  1537. {
  1538. $Log$
  1539. Revision 1.48 1998-11-27 14:50:30 peter
  1540. + open strings, $P switch support
  1541. Revision 1.47 1998/11/26 21:30:03 peter
  1542. * fix for valuepara
  1543. Revision 1.46 1998/11/26 14:39:10 peter
  1544. * ansistring -> pchar fixed
  1545. * ansistring constants fixed
  1546. * ansistring constants are now written once
  1547. Revision 1.45 1998/11/18 15:44:07 peter
  1548. * VALUEPARA for tp7 compatible value parameters
  1549. Revision 1.44 1998/11/16 15:35:36 peter
  1550. * rename laod/copystring -> load/copyshortstring
  1551. * fixed int-bool cnv bug
  1552. + char-ansistring conversion
  1553. Revision 1.43 1998/11/15 16:32:33 florian
  1554. * some stuff of Pavel implement (win32 dll creation)
  1555. * bug with ansistring function results fixed
  1556. Revision 1.42 1998/11/13 15:40:13 pierre
  1557. + added -Se in Makefile cvstest target
  1558. + lexlevel cleanup
  1559. normal_function_level main_program_level and unit_init_level defined
  1560. * tins_cache grown to A_EMMS (gave range check error in asm readers)
  1561. (test added in code !)
  1562. * -Un option was wrong
  1563. * _FAIL and _SELF only keyword inside
  1564. constructors and methods respectively
  1565. Revision 1.41 1998/11/12 11:19:40 pierre
  1566. * fix for first line of function break
  1567. Revision 1.40 1998/11/10 10:09:08 peter
  1568. * va_list -> array of const
  1569. Revision 1.39 1998/11/09 11:44:33 peter
  1570. + va_list for printf support
  1571. Revision 1.38 1998/10/21 15:12:49 pierre
  1572. * bug fix for IOCHECK inside a procedure with iocheck modifier
  1573. * removed the GPF for unexistant overloading
  1574. (firstcall was called with procedinition=nil !)
  1575. * changed typen to what Florian proposed
  1576. gentypenode(p : pdef) sets the typenodetype field
  1577. and resulttype is only set if inside bt_type block !
  1578. Revision 1.37 1998/10/21 08:39:57 florian
  1579. + ansistring operator +
  1580. + $h and string[n] for n>255 added
  1581. * small problem with TP fixed
  1582. Revision 1.36 1998/10/20 08:06:39 pierre
  1583. * several memory corruptions due to double freemem solved
  1584. => never use p^.loc.location:=p^.left^.loc.location;
  1585. + finally I added now by default
  1586. that ra386dir translates global and unit symbols
  1587. + added a first field in tsymtable and
  1588. a nextsym field in tsym
  1589. (this allows to obtain ordered type info for
  1590. records and objects in gdb !)
  1591. Revision 1.35 1998/10/16 08:51:45 peter
  1592. + target_os.stackalignment
  1593. + stack can be aligned at 2 or 4 byte boundaries
  1594. Revision 1.34 1998/10/09 08:56:22 pierre
  1595. * several memory leaks fixed
  1596. Revision 1.33 1998/10/06 17:16:39 pierre
  1597. * some memory leaks fixed (thanks to Peter for heaptrc !)
  1598. Revision 1.32 1998/10/01 09:22:52 peter
  1599. * fixed value openarray
  1600. * ungettemp of arrayconstruct
  1601. Revision 1.31 1998/09/28 16:57:15 pierre
  1602. * changed all length(p^.value_str^) into str_length(p)
  1603. to get it work with and without ansistrings
  1604. * changed sourcefiles field of tmodule to a pointer
  1605. Revision 1.30 1998/09/26 15:03:02 florian
  1606. * small problems with DOM and excpetions fixed (code generation
  1607. of raise was wrong and self was sometimes destroyed :()
  1608. Revision 1.29 1998/09/25 00:04:00 florian
  1609. * problems when calling class methods fixed
  1610. Revision 1.28 1998/09/24 14:27:37 peter
  1611. * some better support for openarray
  1612. Revision 1.27 1998/09/24 09:02:13 peter
  1613. * rewritten isconvertable to use case
  1614. * array of .. and single variable are compatible
  1615. Revision 1.26 1998/09/21 08:45:06 pierre
  1616. + added vmt_offset in tobjectdef.write for fututre use
  1617. (first steps to have objects without vmt if no virtual !!)
  1618. + added fpu_used field for tabstractprocdef :
  1619. sets this level to 2 if the functions return with value in FPU
  1620. (is then set to correct value at parsing of implementation)
  1621. THIS MIGHT refuse some code with FPU expression too complex
  1622. that were accepted before and even in some cases
  1623. that don't overflow in fact
  1624. ( like if f : float; is a forward that finally in implementation
  1625. only uses one fpu register !!)
  1626. Nevertheless I think that it will improve security on
  1627. FPU operations !!
  1628. * most other changes only for UseBrowser code
  1629. (added symtable references for record and objects)
  1630. local switch for refs to args and local of each function
  1631. (static symtable still missing)
  1632. UseBrowser still not stable and probably broken by
  1633. the definition hash array !!
  1634. Revision 1.25 1998/09/20 12:26:35 peter
  1635. * merged fixes
  1636. Revision 1.24 1998/09/17 09:42:10 peter
  1637. + pass_2 for cg386
  1638. * Message() -> CGMessage() for pass_1/pass_2
  1639. Revision 1.23 1998/09/14 10:43:45 peter
  1640. * all internal RTL functions start with FPC_
  1641. Revision 1.22.2.1 1998/09/20 12:20:06 peter
  1642. * Fixed stack not on 4 byte boundary when doing a call
  1643. Revision 1.22 1998/09/04 08:41:37 peter
  1644. * updated some error CGMessages
  1645. Revision 1.21 1998/09/01 12:47:57 peter
  1646. * use pdef^.size instead of orddef^.typ
  1647. Revision 1.20 1998/08/31 12:22:15 peter
  1648. * secondinline moved to cg386inl
  1649. Revision 1.19 1998/08/31 08:52:03 peter
  1650. * fixed error 10 with succ() and pref()
  1651. Revision 1.18 1998/08/20 21:36:38 peter
  1652. * fixed 'with object do' bug
  1653. Revision 1.17 1998/08/19 16:07:36 jonas
  1654. * changed optimizer switches + cleanup of DestroyRefs in daopt386.pas
  1655. Revision 1.16 1998/08/18 09:24:36 pierre
  1656. * small warning position bug fixed
  1657. * support_mmx switches splitting was missing
  1658. * rhide error and warning output corrected
  1659. Revision 1.15 1998/08/13 11:00:09 peter
  1660. * fixed procedure<>procedure construct
  1661. Revision 1.14 1998/08/11 14:05:33 peter
  1662. * fixed sizeof(array of char)
  1663. Revision 1.13 1998/08/10 14:49:45 peter
  1664. + localswitches, moduleswitches, globalswitches splitting
  1665. Revision 1.12 1998/07/30 13:30:31 florian
  1666. * final implemenation of exception support, maybe it needs
  1667. some fixes :)
  1668. Revision 1.11 1998/07/24 22:16:52 florian
  1669. * internal error 10 together with array access fixed. I hope
  1670. that's the final fix.
  1671. Revision 1.10 1998/07/18 22:54:23 florian
  1672. * some ansi/wide/longstring support fixed:
  1673. o parameter passing
  1674. o returning as result from functions
  1675. Revision 1.9 1998/07/07 17:40:37 peter
  1676. * packrecords 4 works
  1677. * word aligning of parameters
  1678. Revision 1.8 1998/07/06 15:51:15 michael
  1679. Added length checking for string reading
  1680. Revision 1.7 1998/07/06 14:19:51 michael
  1681. + Added calls for reading/writing ansistrings
  1682. Revision 1.6 1998/07/01 15:28:48 peter
  1683. + better writeln/readln handling, now 100% like tp7
  1684. Revision 1.5 1998/06/25 14:04:17 peter
  1685. + internal inc/dec
  1686. Revision 1.4 1998/06/25 08:48:06 florian
  1687. * first version of rtti support
  1688. Revision 1.3 1998/06/09 16:01:33 pierre
  1689. + added procedure directive parsing for procvars
  1690. (accepted are popstack cdecl and pascal)
  1691. + added C vars with the following syntax
  1692. var C calias 'true_c_name';(can be followed by external)
  1693. reason is that you must add the Cprefix
  1694. which is target dependent
  1695. Revision 1.2 1998/06/08 13:13:29 pierre
  1696. + temporary variables now in temp_gen.pas unit
  1697. because it is processor independent
  1698. * mppc68k.bat modified to undefine i386 and support_mmx
  1699. (which are defaults for i386)
  1700. Revision 1.1 1998/06/05 17:44:10 peter
  1701. * splitted cgi386
  1702. }