tcmat.pas 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482
  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. globtype,systems,tokens,
  29. cobjects,verbose,globals,
  30. symconst,symtable,aasm,types,
  31. hcodegen,htypechk,pass_1,cpubase;
  32. {*****************************************************************************
  33. FirstModDiv
  34. *****************************************************************************}
  35. procedure firstmoddiv(var p : ptree);
  36. var
  37. t : ptree;
  38. rv,lv : longint;
  39. rd,ld : pdef;
  40. begin
  41. firstpass(p^.left);
  42. firstpass(p^.right);
  43. if codegenerror then
  44. exit;
  45. { check for division by zero }
  46. rv:=p^.right^.value;
  47. lv:=p^.left^.value;
  48. if is_constintnode(p^.right) and (rv=0) then
  49. begin
  50. Message(parser_e_division_by_zero);
  51. { recover }
  52. rv:=1;
  53. end;
  54. if is_constintnode(p^.left) and is_constintnode(p^.right) then
  55. begin
  56. case p^.treetype of
  57. modn : t:=genordinalconstnode(lv mod rv,s32bitdef);
  58. divn : t:=genordinalconstnode(lv div rv,s32bitdef);
  59. end;
  60. disposetree(p);
  61. firstpass(t);
  62. p:=t;
  63. exit;
  64. end;
  65. if (p^.left^.resulttype^.deftype=orddef) and (p^.right^.resulttype^.deftype=orddef) and
  66. (is_64bitint(p^.left^.resulttype) or is_64bitint(p^.right^.resulttype)) then
  67. begin
  68. rd:=p^.right^.resulttype;
  69. ld:=p^.left^.resulttype;
  70. if (porddef(rd)^.typ=s64bit) or (porddef(ld)^.typ=s64bit) then
  71. begin
  72. if (porddef(ld)^.typ<>s64bit) then
  73. begin
  74. p^.left:=gentypeconvnode(p^.left,cs64bitdef);
  75. firstpass(p^.left);
  76. end;
  77. if (porddef(rd)^.typ<>s64bit) then
  78. begin
  79. p^.right:=gentypeconvnode(p^.right,cs64bitdef);
  80. firstpass(p^.right);
  81. end;
  82. calcregisters(p,2,0,0);
  83. end
  84. else if (porddef(rd)^.typ=u64bit) or (porddef(ld)^.typ=u64bit) then
  85. begin
  86. if (porddef(ld)^.typ<>u64bit) then
  87. begin
  88. p^.left:=gentypeconvnode(p^.left,cu64bitdef);
  89. firstpass(p^.left);
  90. end;
  91. if (porddef(rd)^.typ<>u64bit) then
  92. begin
  93. p^.right:=gentypeconvnode(p^.right,cu64bitdef);
  94. firstpass(p^.right);
  95. end;
  96. calcregisters(p,2,0,0);
  97. end;
  98. p^.resulttype:=p^.left^.resulttype;
  99. end
  100. else
  101. begin
  102. if not(p^.right^.resulttype^.deftype=orddef) or
  103. not(porddef(p^.right^.resulttype)^.typ in [s32bit,u32bit]) then
  104. p^.right:=gentypeconvnode(p^.right,s32bitdef);
  105. if not(p^.left^.resulttype^.deftype=orddef) or
  106. not(porddef(p^.left^.resulttype)^.typ in [s32bit,u32bit]) then
  107. p^.left:=gentypeconvnode(p^.left,s32bitdef);
  108. firstpass(p^.left);
  109. firstpass(p^.right);
  110. { the resulttype depends on the right side, because the left becomes }
  111. { always 64 bit }
  112. p^.resulttype:=p^.right^.resulttype;
  113. if codegenerror then
  114. exit;
  115. left_right_max(p);
  116. if p^.left^.registers32<=p^.right^.registers32 then
  117. inc(p^.registers32);
  118. end;
  119. p^.location.loc:=LOC_REGISTER;
  120. end;
  121. {*****************************************************************************
  122. FirstShlShr
  123. *****************************************************************************}
  124. procedure firstshlshr(var p : ptree);
  125. var
  126. t : ptree;
  127. regs : longint;
  128. begin
  129. firstpass(p^.left);
  130. firstpass(p^.right);
  131. if codegenerror then
  132. exit;
  133. if is_constintnode(p^.left) and is_constintnode(p^.right) then
  134. begin
  135. case p^.treetype of
  136. shrn : t:=genordinalconstnode(p^.left^.value shr p^.right^.value,s32bitdef);
  137. shln : t:=genordinalconstnode(p^.left^.value shl p^.right^.value,s32bitdef);
  138. end;
  139. disposetree(p);
  140. firstpass(t);
  141. p:=t;
  142. exit;
  143. end;
  144. { 64 bit ints have their own shift handling }
  145. if not(is_64bitint(p^.left^.resulttype)) then
  146. begin
  147. p^.left:=gentypeconvnode(p^.left,s32bitdef);
  148. firstpass(p^.left);
  149. regs:=1;
  150. p^.resulttype:=s32bitdef;
  151. end
  152. else
  153. begin
  154. p^.resulttype:=p^.left^.resulttype;
  155. regs:=2;
  156. end;
  157. p^.right:=gentypeconvnode(p^.right,s32bitdef);
  158. firstpass(p^.right);
  159. if codegenerror then
  160. exit;
  161. if (p^.right^.treetype<>ordconstn) then
  162. inc(regs);
  163. calcregisters(p,regs,0,0);
  164. p^.location.loc:=LOC_REGISTER;
  165. end;
  166. {*****************************************************************************
  167. FirstUmMinus
  168. *****************************************************************************}
  169. procedure firstumminus(var p : ptree);
  170. var
  171. t : ptree;
  172. minusdef : pprocdef;
  173. begin
  174. firstpass(p^.left);
  175. p^.registers32:=p^.left^.registers32;
  176. p^.registersfpu:=p^.left^.registersfpu;
  177. {$ifdef SUPPORT_MMX}
  178. p^.registersmmx:=p^.left^.registersmmx;
  179. {$endif SUPPORT_MMX}
  180. p^.resulttype:=p^.left^.resulttype;
  181. if codegenerror then
  182. exit;
  183. if is_constintnode(p^.left) then
  184. begin
  185. t:=genordinalconstnode(-p^.left^.value,s32bitdef);
  186. disposetree(p);
  187. firstpass(t);
  188. p:=t;
  189. exit;
  190. end;
  191. { nasm can not cope with negativ reals !! }
  192. if is_constrealnode(p^.left)
  193. {$ifdef i386}
  194. and not(aktoutputformat in [as_i386_nasmcoff,as_i386_nasmelf,as_i386_nasmobj])
  195. {$endif i386}
  196. then
  197. begin
  198. t:=genrealconstnode(-p^.left^.value_real,bestrealdef^);
  199. disposetree(p);
  200. firstpass(t);
  201. p:=t;
  202. exit;
  203. end;
  204. if (p^.left^.resulttype^.deftype=floatdef) then
  205. begin
  206. if pfloatdef(p^.left^.resulttype)^.typ=f32bit then
  207. begin
  208. if (p^.left^.location.loc<>LOC_REGISTER) and
  209. (p^.registers32<1) then
  210. p^.registers32:=1;
  211. p^.location.loc:=LOC_REGISTER;
  212. end
  213. else
  214. p^.location.loc:=LOC_FPU;
  215. end
  216. {$ifdef SUPPORT_MMX}
  217. else if (cs_mmx in aktlocalswitches) and
  218. is_mmx_able_array(p^.left^.resulttype) then
  219. begin
  220. if (p^.left^.location.loc<>LOC_MMXREGISTER) and
  221. (p^.registersmmx<1) then
  222. p^.registersmmx:=1;
  223. { if saturation is on, p^.left^.resulttype isn't
  224. "mmx able" (FK)
  225. if (cs_mmx_saturation in aktlocalswitches^) and
  226. (porddef(parraydef(p^.resulttype)^.definition)^.typ in
  227. [s32bit,u32bit]) then
  228. CGMessage(type_e_mismatch);
  229. }
  230. end
  231. {$endif SUPPORT_MMX}
  232. else if is_64bitint(p^.left^.resulttype) then
  233. begin
  234. firstpass(p^.left);
  235. p^.registersfpu:=p^.left^.registersfpu;
  236. {$ifdef SUPPORT_MMX}
  237. p^.registersmmx:=p^.left^.registersmmx;
  238. {$endif SUPPORT_MMX}
  239. p^.registers32:=p^.left^.registers32;
  240. if codegenerror then
  241. exit;
  242. if (p^.left^.location.loc<>LOC_REGISTER) and
  243. (p^.registers32<2) then
  244. p^.registers32:=2;
  245. p^.location.loc:=LOC_REGISTER;
  246. p^.resulttype:=p^.left^.resulttype;
  247. end
  248. else if (p^.left^.resulttype^.deftype=orddef) then
  249. begin
  250. p^.left:=gentypeconvnode(p^.left,s32bitdef);
  251. firstpass(p^.left);
  252. p^.registersfpu:=p^.left^.registersfpu;
  253. {$ifdef SUPPORT_MMX}
  254. p^.registersmmx:=p^.left^.registersmmx;
  255. {$endif SUPPORT_MMX}
  256. p^.registers32:=p^.left^.registers32;
  257. if codegenerror then
  258. exit;
  259. if (p^.left^.location.loc<>LOC_REGISTER) and
  260. (p^.registers32<1) then
  261. p^.registers32:=1;
  262. p^.location.loc:=LOC_REGISTER;
  263. p^.resulttype:=p^.left^.resulttype;
  264. end
  265. else
  266. begin
  267. if assigned(overloaded_operators[minus]) then
  268. minusdef:=overloaded_operators[minus]^.definition
  269. else
  270. minusdef:=nil;
  271. while assigned(minusdef) do
  272. begin
  273. if (minusdef^.para1^.data=p^.left^.resulttype) and
  274. (minusdef^.para1^.next=nil) then
  275. begin
  276. t:=gencallnode(overloaded_operators[minus],nil);
  277. t^.left:=gencallparanode(p^.left,nil);
  278. putnode(p);
  279. p:=t;
  280. firstpass(p);
  281. exit;
  282. end;
  283. minusdef:=minusdef^.nextoverloaded;
  284. end;
  285. CGMessage(type_e_mismatch);
  286. end;
  287. end;
  288. {*****************************************************************************
  289. FirstNot
  290. *****************************************************************************}
  291. procedure firstnot(var p : ptree);
  292. var
  293. t : ptree;
  294. begin
  295. firstpass(p^.left);
  296. if codegenerror then
  297. exit;
  298. if (p^.left^.treetype=ordconstn) then
  299. begin
  300. if is_boolean(p^.left^.resulttype) then
  301. t:=genordinalconstnode(byte(not(boolean(p^.left^.value))),p^.left^.resulttype)
  302. else
  303. t:=genordinalconstnode(not(p^.left^.value),p^.left^.resulttype);
  304. disposetree(p);
  305. firstpass(t);
  306. p:=t;
  307. exit;
  308. end;
  309. p^.resulttype:=p^.left^.resulttype;
  310. p^.location.loc:=p^.left^.location.loc;
  311. {$ifdef SUPPORT_MMX}
  312. p^.registersmmx:=p^.left^.registersmmx;
  313. {$endif SUPPORT_MMX}
  314. if is_boolean(p^.resulttype) then
  315. begin
  316. p^.registers32:=p^.left^.registers32;
  317. {$ifdef i386}
  318. if p^.left^.location.loc<>LOC_JUMP then
  319. p^.location.loc:=LOC_FLAGS;
  320. {$endif def i386}
  321. if (p^.location.loc in [LOC_REFERENCE,LOC_MEM,LOC_CREGISTER]) then
  322. begin
  323. p^.location.loc:=LOC_REGISTER;
  324. if (p^.registers32<1) then
  325. p^.registers32:=1;
  326. end;
  327. end
  328. else
  329. {$ifdef SUPPORT_MMX}
  330. if (cs_mmx in aktlocalswitches) and
  331. is_mmx_able_array(p^.left^.resulttype) then
  332. begin
  333. if (p^.left^.location.loc<>LOC_MMXREGISTER) and
  334. (p^.registersmmx<1) then
  335. p^.registersmmx:=1;
  336. end
  337. else
  338. {$endif SUPPORT_MMX}
  339. if is_64bitint(p^.left^.resulttype) then
  340. begin
  341. p^.registers32:=p^.left^.registers32;
  342. if (p^.location.loc in [LOC_REFERENCE,LOC_MEM,LOC_CREGISTER]) then
  343. begin
  344. p^.location.loc:=LOC_REGISTER;
  345. if (p^.registers32<2) then
  346. p^.registers32:=2;
  347. end;
  348. end
  349. else
  350. begin
  351. p^.left:=gentypeconvnode(p^.left,s32bitdef);
  352. firstpass(p^.left);
  353. if codegenerror then
  354. exit;
  355. p^.resulttype:=p^.left^.resulttype;
  356. p^.registers32:=p^.left^.registers32;
  357. {$ifdef SUPPORT_MMX}
  358. p^.registersmmx:=p^.left^.registersmmx;
  359. {$endif SUPPORT_MMX}
  360. if (p^.left^.location.loc<>LOC_REGISTER) and
  361. (p^.registers32<1) then
  362. p^.registers32:=1;
  363. p^.location.loc:=LOC_REGISTER;
  364. end;
  365. p^.registersfpu:=p^.left^.registersfpu;
  366. end;
  367. end.
  368. {
  369. $Log$
  370. Revision 1.18 1999-08-04 00:23:43 florian
  371. * renamed i386asm and i386base to cpuasm and cpubase
  372. Revision 1.17 1999/08/03 22:03:34 peter
  373. * moved bitmask constants to sets
  374. * some other type/const renamings
  375. Revision 1.16 1999/06/02 10:11:54 florian
  376. * make cycle fixed i.e. compilation with 0.99.10
  377. * some fixes for qword
  378. * start of register calling conventions
  379. Revision 1.15 1999/05/27 19:45:22 peter
  380. * removed oldasm
  381. * plabel -> pasmlabel
  382. * -a switches to source writing automaticly
  383. * assembler readers OOPed
  384. * asmsymbol automaticly external
  385. * jumptables and other label fixes for asm readers
  386. Revision 1.14 1999/05/06 09:05:38 peter
  387. * generic write_float and str_float
  388. * fixed constant float conversions
  389. Revision 1.13 1999/05/01 13:24:55 peter
  390. * merged nasm compiler
  391. * old asm moved to oldasm/
  392. Revision 1.12 1999/02/22 02:15:53 peter
  393. * updates for ag386bin
  394. Revision 1.11 1999/02/03 10:11:11 pierre
  395. * fix for bug0211 for i386
  396. Revision 1.10 1998/12/11 16:50:24 florian
  397. + typed const int64 and qword
  398. + unary minus-operator q1:=-q2;
  399. + not-operator
  400. Revision 1.9 1998/12/11 16:10:12 florian
  401. + shifting for 64 bit ints added
  402. * bug in getexplicitregister32 fixed: usableregs wasn't decremented !!
  403. Revision 1.8 1998/12/11 00:03:56 peter
  404. + globtype,tokens,version unit splitted from globals
  405. Revision 1.7 1998/11/13 10:16:38 peter
  406. * fixed constant not(boolean)
  407. Revision 1.6 1998/11/05 14:26:01 peter
  408. * fixed shlshr which would push ecx when not needed
  409. Revision 1.5 1998/10/20 13:12:39 peter
  410. * fixed 'not not boolean', the location was not set to register
  411. Revision 1.4 1998/10/13 16:50:25 pierre
  412. * undid some changes of Peter that made the compiler wrong
  413. for m68k (I had to reinsert some ifdefs)
  414. * removed several memory leaks under m68k
  415. * removed the meory leaks for assembler readers
  416. * cross compiling shoud work again better
  417. ( crosscompiling sysamiga works
  418. but as68k still complain about some code !)
  419. Revision 1.3 1998/10/13 13:10:33 peter
  420. * new style for m68k/i386 infos and enums
  421. Revision 1.2 1998/10/11 14:31:20 peter
  422. + checks for division by zero
  423. Revision 1.1 1998/09/23 20:42:24 peter
  424. * splitted pass_1
  425. }