tcmat.pas 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  1. {
  2. $Id$
  3. Copyright (c) 1993-98 by Florian Klaempfl
  4. Type checking and register allocation for math 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 tcmat;
  19. interface
  20. uses
  21. tree;
  22. procedure firstmoddiv(var p : ptree);
  23. procedure firstshlshr(var p : ptree);
  24. procedure firstumminus(var p : ptree);
  25. procedure firstnot(var p : ptree);
  26. implementation
  27. uses
  28. cobjects,verbose,globals,systems,
  29. symtable,aasm,types,
  30. hcodegen,htypechk,pass_1
  31. {$ifdef i386}
  32. ,i386
  33. {$endif}
  34. {$ifdef m68k}
  35. ,m68k
  36. {$endif}
  37. ;
  38. {*****************************************************************************
  39. FirstModDiv
  40. *****************************************************************************}
  41. procedure firstmoddiv(var p : ptree);
  42. var
  43. t : ptree;
  44. rv,lv : longint;
  45. begin
  46. firstpass(p^.left);
  47. firstpass(p^.right);
  48. if codegenerror then
  49. exit;
  50. { check for division by zero }
  51. rv:=p^.right^.value;
  52. lv:=p^.left^.value;
  53. if is_constintnode(p^.right) and (rv=0) then
  54. begin
  55. Message(parser_e_division_by_zero);
  56. { recover }
  57. rv:=1;
  58. end;
  59. if is_constintnode(p^.left) and is_constintnode(p^.right) then
  60. begin
  61. case p^.treetype of
  62. modn : t:=genordinalconstnode(lv mod rv,s32bitdef);
  63. divn : t:=genordinalconstnode(lv div rv,s32bitdef);
  64. end;
  65. disposetree(p);
  66. firstpass(t);
  67. p:=t;
  68. exit;
  69. end;
  70. if not(p^.right^.resulttype^.deftype=orddef) or
  71. not(porddef(p^.right^.resulttype)^.typ in [s32bit,u32bit]) then
  72. p^.right:=gentypeconvnode(p^.right,s32bitdef);
  73. if not(p^.left^.resulttype^.deftype=orddef) or
  74. not(porddef(p^.left^.resulttype)^.typ in [s32bit,u32bit]) then
  75. p^.left:=gentypeconvnode(p^.left,s32bitdef);
  76. firstpass(p^.left);
  77. firstpass(p^.right);
  78. { the resulttype depends on the right side, because the left becomes }
  79. { always 64 bit }
  80. p^.resulttype:=p^.right^.resulttype;
  81. if codegenerror then
  82. exit;
  83. left_right_max(p);
  84. if p^.left^.registers32<=p^.right^.registers32 then
  85. inc(p^.registers32);
  86. p^.location.loc:=LOC_REGISTER;
  87. end;
  88. {*****************************************************************************
  89. FirstShlShr
  90. *****************************************************************************}
  91. procedure firstshlshr(var p : ptree);
  92. var
  93. t : ptree;
  94. regs : longint;
  95. begin
  96. firstpass(p^.left);
  97. firstpass(p^.right);
  98. if codegenerror then
  99. exit;
  100. if is_constintnode(p^.left) and is_constintnode(p^.right) then
  101. begin
  102. case p^.treetype of
  103. shrn : t:=genordinalconstnode(p^.left^.value shr p^.right^.value,s32bitdef);
  104. shln : t:=genordinalconstnode(p^.left^.value shl p^.right^.value,s32bitdef);
  105. end;
  106. disposetree(p);
  107. firstpass(t);
  108. p:=t;
  109. exit;
  110. end;
  111. p^.right:=gentypeconvnode(p^.right,s32bitdef);
  112. p^.left:=gentypeconvnode(p^.left,s32bitdef);
  113. firstpass(p^.left);
  114. firstpass(p^.right);
  115. if codegenerror then
  116. exit;
  117. regs:=1;
  118. if (p^.right^.treetype<>ordconstn) then
  119. inc(regs);
  120. calcregisters(p,regs,0,0);
  121. p^.resulttype:=s32bitdef;
  122. p^.location.loc:=LOC_REGISTER;
  123. end;
  124. {*****************************************************************************
  125. FirstUmMinus
  126. *****************************************************************************}
  127. procedure firstumminus(var p : ptree);
  128. var
  129. t : ptree;
  130. minusdef : pprocdef;
  131. begin
  132. firstpass(p^.left);
  133. p^.registers32:=p^.left^.registers32;
  134. p^.registersfpu:=p^.left^.registersfpu;
  135. {$ifdef SUPPORT_MMX}
  136. p^.registersmmx:=p^.left^.registersmmx;
  137. {$endif SUPPORT_MMX}
  138. p^.resulttype:=p^.left^.resulttype;
  139. if codegenerror then
  140. exit;
  141. if is_constintnode(p^.left) then
  142. begin
  143. t:=genordinalconstnode(-p^.left^.value,s32bitdef);
  144. disposetree(p);
  145. firstpass(t);
  146. p:=t;
  147. exit;
  148. end;
  149. { nasm can not cope with negativ reals !! }
  150. if is_constrealnode(p^.left)
  151. {$ifdef i386}
  152. and not(aktoutputformat in [as_i386_nasmcoff,as_i386_nasmelf,as_i386_nasmobj])
  153. {$endif i386}
  154. then
  155. begin
  156. t:=genrealconstnode(-p^.left^.value_real);
  157. disposetree(p);
  158. firstpass(t);
  159. p:=t;
  160. exit;
  161. end;
  162. if (p^.left^.resulttype^.deftype=floatdef) then
  163. begin
  164. if pfloatdef(p^.left^.resulttype)^.typ=f32bit then
  165. begin
  166. if (p^.left^.location.loc<>LOC_REGISTER) and
  167. (p^.registers32<1) then
  168. p^.registers32:=1;
  169. p^.location.loc:=LOC_REGISTER;
  170. end
  171. else
  172. p^.location.loc:=LOC_FPU;
  173. end
  174. {$ifdef SUPPORT_MMX}
  175. else if (cs_mmx in aktlocalswitches) and
  176. is_mmx_able_array(p^.left^.resulttype) then
  177. begin
  178. if (p^.left^.location.loc<>LOC_MMXREGISTER) and
  179. (p^.registersmmx<1) then
  180. p^.registersmmx:=1;
  181. { if saturation is on, p^.left^.resulttype isn't
  182. "mmx able" (FK)
  183. if (cs_mmx_saturation in aktlocalswitches^) and
  184. (porddef(parraydef(p^.resulttype)^.definition)^.typ in
  185. [s32bit,u32bit]) then
  186. CGMessage(type_e_mismatch);
  187. }
  188. end
  189. {$endif SUPPORT_MMX}
  190. else if (p^.left^.resulttype^.deftype=orddef) then
  191. begin
  192. p^.left:=gentypeconvnode(p^.left,s32bitdef);
  193. firstpass(p^.left);
  194. p^.registersfpu:=p^.left^.registersfpu;
  195. {$ifdef SUPPORT_MMX}
  196. p^.registersmmx:=p^.left^.registersmmx;
  197. {$endif SUPPORT_MMX}
  198. p^.registers32:=p^.left^.registers32;
  199. if codegenerror then
  200. exit;
  201. if (p^.left^.location.loc<>LOC_REGISTER) and
  202. (p^.registers32<1) then
  203. p^.registers32:=1;
  204. p^.location.loc:=LOC_REGISTER;
  205. p^.resulttype:=p^.left^.resulttype;
  206. end
  207. else
  208. begin
  209. if assigned(overloaded_operators[minus]) then
  210. minusdef:=overloaded_operators[minus]^.definition
  211. else
  212. minusdef:=nil;
  213. while assigned(minusdef) do
  214. begin
  215. if (minusdef^.para1^.data=p^.left^.resulttype) and
  216. (minusdef^.para1^.next=nil) then
  217. begin
  218. t:=gencallnode(overloaded_operators[minus],nil);
  219. t^.left:=gencallparanode(p^.left,nil);
  220. putnode(p);
  221. p:=t;
  222. firstpass(p);
  223. exit;
  224. end;
  225. minusdef:=minusdef^.nextoverloaded;
  226. end;
  227. CGMessage(type_e_mismatch);
  228. end;
  229. end;
  230. {*****************************************************************************
  231. FirstNot
  232. *****************************************************************************}
  233. procedure firstnot(var p : ptree);
  234. var
  235. t : ptree;
  236. begin
  237. firstpass(p^.left);
  238. if codegenerror then
  239. exit;
  240. if (p^.left^.treetype=ordconstn) then
  241. begin
  242. if is_boolean(p^.left^.resulttype) then
  243. t:=genordinalconstnode(byte(not(boolean(p^.left^.value))),p^.left^.resulttype)
  244. else
  245. t:=genordinalconstnode(not(p^.left^.value),p^.left^.resulttype);
  246. disposetree(p);
  247. firstpass(t);
  248. p:=t;
  249. exit;
  250. end;
  251. p^.resulttype:=p^.left^.resulttype;
  252. p^.location.loc:=p^.left^.location.loc;
  253. {$ifdef SUPPORT_MMX}
  254. p^.registersmmx:=p^.left^.registersmmx;
  255. {$endif SUPPORT_MMX}
  256. if is_boolean(p^.resulttype) then
  257. begin
  258. p^.registers32:=p^.left^.registers32;
  259. if (p^.location.loc in [LOC_REFERENCE,LOC_MEM,LOC_CREGISTER]) then
  260. begin
  261. p^.location.loc:=LOC_REGISTER;
  262. if (p^.registers32<1) then
  263. p^.registers32:=1;
  264. end;
  265. end
  266. else
  267. {$ifdef SUPPORT_MMX}
  268. if (cs_mmx in aktlocalswitches) and
  269. is_mmx_able_array(p^.left^.resulttype) then
  270. begin
  271. if (p^.left^.location.loc<>LOC_MMXREGISTER) and
  272. (p^.registersmmx<1) then
  273. p^.registersmmx:=1;
  274. end
  275. else
  276. {$endif SUPPORT_MMX}
  277. begin
  278. p^.left:=gentypeconvnode(p^.left,s32bitdef);
  279. firstpass(p^.left);
  280. if codegenerror then
  281. exit;
  282. p^.resulttype:=p^.left^.resulttype;
  283. p^.registers32:=p^.left^.registers32;
  284. {$ifdef SUPPORT_MMX}
  285. p^.registersmmx:=p^.left^.registersmmx;
  286. {$endif SUPPORT_MMX}
  287. if (p^.left^.location.loc<>LOC_REGISTER) and
  288. (p^.registers32<1) then
  289. p^.registers32:=1;
  290. p^.location.loc:=LOC_REGISTER;
  291. end;
  292. p^.registersfpu:=p^.left^.registersfpu;
  293. end;
  294. end.
  295. {
  296. $Log$
  297. Revision 1.7 1998-11-13 10:16:38 peter
  298. * fixed constant not(boolean)
  299. Revision 1.6 1998/11/05 14:26:01 peter
  300. * fixed shlshr which would push ecx when not needed
  301. Revision 1.5 1998/10/20 13:12:39 peter
  302. * fixed 'not not boolean', the location was not set to register
  303. Revision 1.4 1998/10/13 16:50:25 pierre
  304. * undid some changes of Peter that made the compiler wrong
  305. for m68k (I had to reinsert some ifdefs)
  306. * removed several memory leaks under m68k
  307. * removed the meory leaks for assembler readers
  308. * cross compiling shoud work again better
  309. ( crosscompiling sysamiga works
  310. but as68k still complain about some code !)
  311. Revision 1.3 1998/10/13 13:10:33 peter
  312. * new style for m68k/i386 infos and enums
  313. Revision 1.2 1998/10/11 14:31:20 peter
  314. + checks for division by zero
  315. Revision 1.1 1998/09/23 20:42:24 peter
  316. * splitted pass_1
  317. }