cg386cal.pas 84 KB

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