nadd.pas 50 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 by Florian Klaempfl
  4. Type checking and register allocation for add 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 nadd;
  19. interface
  20. uses
  21. node;
  22. type
  23. taddnode = class(tbinopnode)
  24. procedure make_bool_equal_size;
  25. function firstpass : tnode;override;
  26. end;
  27. tcaddnode : class of taddnode;
  28. var
  29. { caddnode is used to create nodes of the add type }
  30. { the virtual constructor allows to assign }
  31. { another class type to caddnode => processor }
  32. { specific node types can be created }
  33. caddnode : tcaddnode;
  34. function isbinaryoverloaded(var p : ptree) : boolean;
  35. implementation
  36. uses
  37. globtype,systems,tokens,
  38. cobjects,verbose,globals,
  39. symconst,symtable,aasm,types,
  40. cpuinfo,
  41. {$ifdef newcg}
  42. cgbase,
  43. {$else newcg}
  44. hcodegen,
  45. {$endif newcg}
  46. htypechk,pass_1,
  47. cpubase,tccnv
  48. ;
  49. function isbinaryoverloaded(var p : ptree) : boolean;
  50. var
  51. rd,ld : pdef;
  52. t : ptree;
  53. optoken : ttoken;
  54. begin
  55. isbinaryoverloaded:=false;
  56. { overloaded operator ? }
  57. { load easier access variables }
  58. rd:=p^.right^.resulttype;
  59. ld:=p^.left^.resulttype;
  60. if isbinaryoperatoroverloadable(ld,rd,voiddef,p^.treetype) then
  61. begin
  62. isbinaryoverloaded:=true;
  63. {!!!!!!!!! handle paras }
  64. case p^.treetype of
  65. { the nil as symtable signs firstcalln that this is
  66. an overloaded operator }
  67. addn:
  68. optoken:=_PLUS;
  69. subn:
  70. optoken:=_MINUS;
  71. muln:
  72. optoken:=_STAR;
  73. starstarn:
  74. optoken:=_STARSTAR;
  75. slashn:
  76. optoken:=_SLASH;
  77. ltn:
  78. optoken:=tokens._lt;
  79. gtn:
  80. optoken:=tokens._gt;
  81. lten:
  82. optoken:=_lte;
  83. gten:
  84. optoken:=_gte;
  85. equaln,unequaln :
  86. optoken:=_EQUAL;
  87. symdifn :
  88. optoken:=_SYMDIF;
  89. modn :
  90. optoken:=_OP_MOD;
  91. orn :
  92. optoken:=_OP_OR;
  93. xorn :
  94. optoken:=_OP_XOR;
  95. andn :
  96. optoken:=_OP_AND;
  97. divn :
  98. optoken:=_OP_DIV;
  99. shln :
  100. optoken:=_OP_SHL;
  101. shrn :
  102. optoken:=_OP_SHR;
  103. else
  104. exit;
  105. end;
  106. t:=gencallnode(overloaded_operators[optoken],nil);
  107. { we have to convert p^.left and p^.right into
  108. callparanodes }
  109. if t^.symtableprocentry=nil then
  110. begin
  111. CGMessage(parser_e_operator_not_overloaded);
  112. putnode(t);
  113. end
  114. else
  115. begin
  116. inc(t^.symtableprocentry^.refs);
  117. t^.left:=gencallparanode(p^.left,nil);
  118. t^.left:=gencallparanode(p^.right,t^.left);
  119. if p^.treetype=unequaln then
  120. t:=gensinglenode(notn,t);
  121. firstpass(t);
  122. putnode(p);
  123. p:=t;
  124. end;
  125. end;
  126. end;
  127. {*****************************************************************************
  128. FirstAdd
  129. *****************************************************************************}
  130. {$ifdef fpc}
  131. {$maxfpuregisters 0}
  132. {$endif fpc}
  133. procedure taddnode.make_bool_equal_size;
  134. begin
  135. if porddef(left^.resulttype)^.typ>porddef(right^.resulttype)^.typ then
  136. begin
  137. right:=gentypeconvnode(right,porddef(left^.resulttype));
  138. right^.convtyp:=tc_bool_2_int;
  139. right^.explizit:=true;
  140. firstpass(right);
  141. end
  142. else
  143. if porddef(left^.resulttype)^.typ<porddef(right^.resulttype)^.typ then
  144. begin
  145. left:=gentypeconvnode(left,porddef(right^.resulttype));
  146. left^.convtyp:=tc_bool_2_int;
  147. left^.explizit:=true;
  148. firstpass(left);
  149. end;
  150. end;
  151. function taddnode.pass_1 : tnode;
  152. var
  153. t,hp : ptree;
  154. ot,
  155. lt,rt : ttreetyp;
  156. rv,lv : TConstExprInt;
  157. rvd,lvd : bestreal;
  158. resdef,
  159. rd,ld : pdef;
  160. tempdef : pdef;
  161. concatstrings : boolean;
  162. { to evalute const sets }
  163. resultset : pconstset;
  164. i : longint;
  165. b : boolean;
  166. convdone : boolean;
  167. s1,s2 : pchar;
  168. l1,l2 : longint;
  169. begin
  170. pass_1:=nil;
  171. { first do the two subtrees }
  172. firstpass(left);
  173. firstpass(right);
  174. if codegenerror then
  175. exit;
  176. { convert array constructors to sets, because there is no other operator
  177. possible for array constructors }
  178. if is_array_constructor(left^.resulttype) then
  179. arrayconstructor_to_set(left);
  180. if is_array_constructor(right^.resulttype) then
  181. arrayconstructor_to_set(right);
  182. { both left and right need to be valid }
  183. set_varstate(left,true);
  184. set_varstate(right,true);
  185. { load easier access variables }
  186. lt:=left^.treetype;
  187. rt:=right^.treetype;
  188. rd:=right^.resulttype;
  189. ld:=left^.resulttype;
  190. convdone:=false;
  191. if isbinaryoverloaded(p) then
  192. exit;
  193. { compact consts }
  194. { convert int consts to real consts, if the }
  195. { other operand is a real const }
  196. if (rt=realconstn) and is_constintnode(left) then
  197. begin
  198. t:=genrealconstnode(left^.value,right^.resulttype);
  199. disposetree(left);
  200. left:=t;
  201. lt:=realconstn;
  202. end;
  203. if (lt=realconstn) and is_constintnode(right) then
  204. begin
  205. t:=genrealconstnode(right^.value,left^.resulttype);
  206. disposetree(right);
  207. right:=t;
  208. rt:=realconstn;
  209. end;
  210. { both are int constants, also allow operations on two equal enums
  211. in fpc mode (Needed for conversion of C code) }
  212. if ((lt=ordconstn) and (rt=ordconstn)) and
  213. ((is_constintnode(left) and is_constintnode(right)) or
  214. (is_constboolnode(left) and is_constboolnode(right) and
  215. (treetype in [ltn,lten,gtn,gten,equaln,unequaln,andn,xorn,orn]))) then
  216. begin
  217. { return a boolean for boolean operations (and,xor,or) }
  218. if is_constboolnode(left) then
  219. resdef:=booldef
  220. else
  221. resdef:=s32bitdef;
  222. lv:=left^.value;
  223. rv:=right^.value;
  224. case treetype of
  225. addn : t:=genordinalconstnode(lv+rv,resdef);
  226. subn : t:=genordinalconstnode(lv-rv,resdef);
  227. muln : t:=genordinalconstnode(lv*rv,resdef);
  228. xorn : t:=genordinalconstnode(lv xor rv,resdef);
  229. orn : t:=genordinalconstnode(lv or rv,resdef);
  230. andn : t:=genordinalconstnode(lv and rv,resdef);
  231. ltn : t:=genordinalconstnode(ord(lv<rv),booldef);
  232. lten : t:=genordinalconstnode(ord(lv<=rv),booldef);
  233. gtn : t:=genordinalconstnode(ord(lv>rv),booldef);
  234. gten : t:=genordinalconstnode(ord(lv>=rv),booldef);
  235. equaln : t:=genordinalconstnode(ord(lv=rv),booldef);
  236. unequaln : t:=genordinalconstnode(ord(lv<>rv),booldef);
  237. slashn : begin
  238. { int/int becomes a real }
  239. if int(rv)=0 then
  240. begin
  241. Message(parser_e_invalid_float_operation);
  242. t:=genrealconstnode(0,bestrealdef^);
  243. end
  244. else
  245. t:=genrealconstnode(int(lv)/int(rv),bestrealdef^);
  246. firstpass(t);
  247. end;
  248. else
  249. CGMessage(type_e_mismatch);
  250. end;
  251. firstpass(t);
  252. { the caller disposes the old tree }
  253. pass_1:=t;
  254. exit;
  255. end;
  256. { both real constants ? }
  257. if (lt=realconstn) and (rt=realconstn) then
  258. begin
  259. lvd:=left^.value_real;
  260. rvd:=right^.value_real;
  261. case treetype of
  262. addn : t:=genrealconstnode(lvd+rvd,bestrealdef^);
  263. subn : t:=genrealconstnode(lvd-rvd,bestrealdef^);
  264. muln : t:=genrealconstnode(lvd*rvd,bestrealdef^);
  265. starstarn,
  266. caretn : begin
  267. if lvd<0 then
  268. begin
  269. Message(parser_e_invalid_float_operation);
  270. t:=genrealconstnode(0,bestrealdef^);
  271. end
  272. else if lvd=0 then
  273. t:=genrealconstnode(1.0,bestrealdef^)
  274. else
  275. t:=genrealconstnode(exp(ln(lvd)*rvd),bestrealdef^);
  276. end;
  277. slashn :
  278. begin
  279. if rvd=0 then
  280. begin
  281. Message(parser_e_invalid_float_operation);
  282. t:=genrealconstnode(0,bestrealdef^);
  283. end
  284. else
  285. t:=genrealconstnode(lvd/rvd,bestrealdef^);
  286. end;
  287. ltn : t:=genordinalconstnode(ord(lvd<rvd),booldef);
  288. lten : t:=genordinalconstnode(ord(lvd<=rvd),booldef);
  289. gtn : t:=genordinalconstnode(ord(lvd>rvd),booldef);
  290. gten : t:=genordinalconstnode(ord(lvd>=rvd),booldef);
  291. equaln : t:=genordinalconstnode(ord(lvd=rvd),booldef);
  292. unequaln : t:=genordinalconstnode(ord(lvd<>rvd),booldef);
  293. else
  294. CGMessage(type_e_mismatch);
  295. end;
  296. firstpass(t);
  297. pass_1:=t;
  298. exit;
  299. end;
  300. { concating strings ? }
  301. concatstrings:=false;
  302. s1:=nil;
  303. s2:=nil;
  304. if (lt=ordconstn) and (rt=ordconstn) and
  305. is_char(ld) and is_char(rd) then
  306. begin
  307. s1:=strpnew(char(byte(left^.value)));
  308. s2:=strpnew(char(byte(right^.value)));
  309. l1:=1;
  310. l2:=1;
  311. concatstrings:=true;
  312. end
  313. else
  314. if (lt=stringconstn) and (rt=ordconstn) and is_char(rd) then
  315. begin
  316. s1:=getpcharcopy(left);
  317. l1:=left^.length;
  318. s2:=strpnew(char(byte(right^.value)));
  319. l2:=1;
  320. concatstrings:=true;
  321. end
  322. else
  323. if (lt=ordconstn) and (rt=stringconstn) and is_char(ld) then
  324. begin
  325. s1:=strpnew(char(byte(left^.value)));
  326. l1:=1;
  327. s2:=getpcharcopy(right);
  328. l2:=right^.length;
  329. concatstrings:=true;
  330. end
  331. else if (lt=stringconstn) and (rt=stringconstn) then
  332. begin
  333. s1:=getpcharcopy(left);
  334. l1:=left^.length;
  335. s2:=getpcharcopy(right);
  336. l2:=right^.length;
  337. concatstrings:=true;
  338. end;
  339. { I will need to translate all this to ansistrings !!! }
  340. if concatstrings then
  341. begin
  342. case treetype of
  343. addn :
  344. t:=genpcharconstnode(concatansistrings(s1,s2,l1,l2),l1+l2);
  345. ltn :
  346. t:=genordinalconstnode(byte(compareansistrings(s1,s2,l1,l2)<0),booldef);
  347. lten :
  348. t:=genordinalconstnode(byte(compareansistrings(s1,s2,l1,l2)<=0),booldef);
  349. gtn :
  350. t:=genordinalconstnode(byte(compareansistrings(s1,s2,l1,l2)>0),booldef);
  351. gten :
  352. t:=genordinalconstnode(byte(compareansistrings(s1,s2,l1,l2)>=0),booldef);
  353. equaln :
  354. t:=genordinalconstnode(byte(compareansistrings(s1,s2,l1,l2)=0),booldef);
  355. unequaln :
  356. t:=genordinalconstnode(byte(compareansistrings(s1,s2,l1,l2)<>0),booldef);
  357. end;
  358. ansistringdispose(s1,l1);
  359. ansistringdispose(s2,l2);
  360. firstpass(t);
  361. pass_1:=t;
  362. exit;
  363. end;
  364. { if both are orddefs then check sub types }
  365. if (ld^.deftype=orddef) and (rd^.deftype=orddef) then
  366. begin
  367. { 2 booleans ? }
  368. if is_boolean(ld) and is_boolean(rd) then
  369. begin
  370. case treetype of
  371. andn,
  372. orn:
  373. begin
  374. make_bool_equal_size(p);
  375. calcregisters(p,0,0,0);
  376. location.loc:=LOC_JUMP;
  377. end;
  378. xorn,ltn,lten,gtn,gten:
  379. begin
  380. make_bool_equal_size(p);
  381. if (left^.location.loc in [LOC_JUMP,LOC_FLAGS]) and
  382. (left^.location.loc in [LOC_JUMP,LOC_FLAGS]) then
  383. calcregisters(p,2,0,0)
  384. else
  385. calcregisters(p,1,0,0);
  386. end;
  387. unequaln,
  388. equaln:
  389. begin
  390. make_bool_equal_size(p);
  391. { Remove any compares with constants }
  392. if (left^.treetype=ordconstn) then
  393. begin
  394. hp:=right;
  395. b:=(left^.value<>0);
  396. ot:=treetype;
  397. disposetree(left);
  398. putnode(p);
  399. p:=hp;
  400. if (not(b) and (ot=equaln)) or
  401. (b and (ot=unequaln)) then
  402. begin
  403. p:=gensinglenode(notn,p);
  404. firstpass(p);
  405. end;
  406. exit;
  407. end;
  408. if (right^.treetype=ordconstn) then
  409. begin
  410. hp:=left;
  411. b:=(right^.value<>0);
  412. ot:=treetype;
  413. disposetree(right);
  414. putnode(p);
  415. p:=hp;
  416. if (not(b) and (ot=equaln)) or
  417. (b and (ot=unequaln)) then
  418. begin
  419. p:=gensinglenode(notn,p);
  420. firstpass(p);
  421. end;
  422. exit;
  423. end;
  424. if (left^.location.loc in [LOC_JUMP,LOC_FLAGS]) and
  425. (left^.location.loc in [LOC_JUMP,LOC_FLAGS]) then
  426. calcregisters(p,2,0,0)
  427. else
  428. calcregisters(p,1,0,0);
  429. end;
  430. else
  431. CGMessage(type_e_mismatch);
  432. end;
  433. { these one can't be in flags! }
  434. if treetype in [xorn,unequaln,equaln] then
  435. begin
  436. if left^.location.loc=LOC_FLAGS then
  437. begin
  438. left:=gentypeconvnode(left,porddef(left^.resulttype));
  439. left^.convtyp:=tc_bool_2_int;
  440. left^.explizit:=true;
  441. firstpass(left);
  442. end;
  443. if right^.location.loc=LOC_FLAGS then
  444. begin
  445. right:=gentypeconvnode(right,porddef(right^.resulttype));
  446. right^.convtyp:=tc_bool_2_int;
  447. right^.explizit:=true;
  448. firstpass(right);
  449. end;
  450. { readjust registers }
  451. calcregisters(p,1,0,0);
  452. end;
  453. convdone:=true;
  454. end
  455. else
  456. { Both are chars? only convert to shortstrings for addn }
  457. if is_char(rd) and is_char(ld) then
  458. begin
  459. if treetype=addn then
  460. begin
  461. left:=gentypeconvnode(left,cshortstringdef);
  462. right:=gentypeconvnode(right,cshortstringdef);
  463. firstpass(left);
  464. firstpass(right);
  465. { here we call STRCOPY }
  466. procinfo^.flags:=procinfo^.flags or pi_do_call;
  467. calcregisters(p,0,0,0);
  468. location.loc:=LOC_MEM;
  469. end
  470. else
  471. calcregisters(p,1,0,0);
  472. convdone:=true;
  473. end
  474. { is there a 64 bit type ? }
  475. else if ((porddef(rd)^.typ=s64bit) or (porddef(ld)^.typ=s64bit)) and
  476. { the / operator is handled later }
  477. (treetype<>slashn) then
  478. begin
  479. if (porddef(ld)^.typ<>s64bit) then
  480. begin
  481. left:=gentypeconvnode(left,cs64bitdef);
  482. firstpass(left);
  483. end;
  484. if (porddef(rd)^.typ<>s64bit) then
  485. begin
  486. right:=gentypeconvnode(right,cs64bitdef);
  487. firstpass(right);
  488. end;
  489. calcregisters(p,2,0,0);
  490. convdone:=true;
  491. end
  492. else if ((porddef(rd)^.typ=u64bit) or (porddef(ld)^.typ=u64bit)) and
  493. { the / operator is handled later }
  494. (treetype<>slashn) then
  495. begin
  496. if (porddef(ld)^.typ<>u64bit) then
  497. begin
  498. left:=gentypeconvnode(left,cu64bitdef);
  499. firstpass(left);
  500. end;
  501. if (porddef(rd)^.typ<>u64bit) then
  502. begin
  503. right:=gentypeconvnode(right,cu64bitdef);
  504. firstpass(right);
  505. end;
  506. calcregisters(p,2,0,0);
  507. convdone:=true;
  508. end
  509. else
  510. { is there a cardinal? }
  511. if ((porddef(rd)^.typ=u32bit) or (porddef(ld)^.typ=u32bit)) and
  512. { the / operator is handled later }
  513. (treetype<>slashn) then
  514. begin
  515. { convert constants to u32bit }
  516. {$ifndef cardinalmulfix}
  517. if (porddef(ld)^.typ<>u32bit) then
  518. begin
  519. { s32bit will be used for when the other is also s32bit }
  520. { the following line doesn't make any sense: it's the same as }
  521. { if ((porddef(rd)^.typ=u32bit) or (porddef(ld)^.typ=u32bit)) and }
  522. { (porddef(ld)^.typ<>u32bit) and (porddef(rd)^.typ=s32bit) then }
  523. { which can be simplified to }
  524. { if ((porddef(rd)^.typ=u32bit) and (porddef(rd)^.typ=s32bit) then }
  525. { which can never be true (JM) }
  526. if (porddef(rd)^.typ=s32bit) and (lt<>ordconstn) then
  527. left:=gentypeconvnode(left,s32bitdef)
  528. else
  529. left:=gentypeconvnode(left,u32bitdef);
  530. firstpass(left);
  531. end;
  532. if (porddef(rd)^.typ<>u32bit) then
  533. begin
  534. { s32bit will be used for when the other is also s32bit }
  535. if (porddef(ld)^.typ=s32bit) and (rt<>ordconstn) then
  536. right:=gentypeconvnode(right,s32bitdef)
  537. else
  538. right:=gentypeconvnode(right,u32bitdef);
  539. firstpass(right);
  540. end;
  541. {$else cardinalmulfix}
  542. { only do a conversion if the nodes have different signs }
  543. if (porddef(rd)^.typ=u32bit) xor (porddef(ld)^.typ=u32bit) then
  544. if (porddef(rd)^.typ=u32bit) then
  545. begin
  546. { can we make them both unsigned? }
  547. if (porddef(ld)^.typ in [u8bit,u16bit]) or
  548. (is_constintnode(p^.left) and
  549. (p^.treetype <> subn) and
  550. (p^.left^.value > 0)) then
  551. p^.left:=gentypeconvnode(p^.left,u32bitdef)
  552. else
  553. p^.left:=gentypeconvnode(p^.left,s32bitdef);
  554. firstpass(p^.left);
  555. end
  556. else {if (porddef(ld)^.typ=u32bit) then}
  557. begin
  558. { can we make them both unsigned? }
  559. if (porddef(rd)^.typ in [u8bit,u16bit]) or
  560. (is_constintnode(p^.right) and
  561. (p^.right^.value > 0)) then
  562. p^.right:=gentypeconvnode(p^.right,u32bitdef)
  563. else
  564. p^.right:=gentypeconvnode(p^.right,s32bitdef);
  565. firstpass(p^.right);
  566. end;
  567. {$endif cardinalmulfix}
  568. calcregisters(p,1,0,0);
  569. { for unsigned mul we need an extra register }
  570. { registers32:=left^.registers32+right^.registers32; }
  571. if treetype=muln then
  572. inc(registers32);
  573. convdone:=true;
  574. end;
  575. end
  576. else
  577. { left side a setdef, must be before string processing,
  578. else array constructor can be seen as array of char (PFV) }
  579. if (ld^.deftype=setdef) {or is_array_constructor(ld)} then
  580. begin
  581. { trying to add a set element? }
  582. if (treetype=addn) and (rd^.deftype<>setdef) then
  583. begin
  584. if (rt=setelementn) then
  585. begin
  586. if not(is_equal(psetdef(ld)^.elementtype.def,rd)) then
  587. CGMessage(type_e_set_element_are_not_comp);
  588. end
  589. else
  590. CGMessage(type_e_mismatch)
  591. end
  592. else
  593. begin
  594. if not(treetype in [addn,subn,symdifn,muln,equaln,unequaln
  595. {$IfNDef NoSetInclusion}
  596. ,lten,gten
  597. {$EndIf NoSetInclusion}
  598. ]) then
  599. CGMessage(type_e_set_operation_unknown);
  600. { right def must be a also be set }
  601. if (rd^.deftype<>setdef) or not(is_equal(rd,ld)) then
  602. CGMessage(type_e_set_element_are_not_comp);
  603. end;
  604. { ranges require normsets }
  605. if (psetdef(ld)^.settype=smallset) and
  606. (rt=setelementn) and
  607. assigned(right^.right) then
  608. begin
  609. { generate a temporary normset def }
  610. tempdef:=new(psetdef,init(psetdef(ld)^.elementtype.def,255));
  611. left:=gentypeconvnode(left,tempdef);
  612. firstpass(left);
  613. dispose(tempdef,done);
  614. ld:=left^.resulttype;
  615. end;
  616. { if the destination is not a smallset then insert a typeconv
  617. which loads a smallset into a normal set }
  618. if (psetdef(ld)^.settype<>smallset) and
  619. (psetdef(rd)^.settype=smallset) then
  620. begin
  621. if (right^.treetype=setconstn) then
  622. begin
  623. t:=gensetconstnode(right^.value_set,psetdef(left^.resulttype));
  624. t^.left:=right^.left;
  625. putnode(right);
  626. right:=t;
  627. end
  628. else
  629. right:=gentypeconvnode(right,psetdef(left^.resulttype));
  630. firstpass(right);
  631. end;
  632. { do constant evaluation }
  633. if (right^.treetype=setconstn) and
  634. not assigned(right^.left) and
  635. (left^.treetype=setconstn) and
  636. not assigned(left^.left) then
  637. begin
  638. new(resultset);
  639. case treetype of
  640. addn : begin
  641. for i:=0 to 31 do
  642. resultset^[i]:=
  643. right^.value_set^[i] or left^.value_set^[i];
  644. t:=gensetconstnode(resultset,psetdef(ld));
  645. end;
  646. muln : begin
  647. for i:=0 to 31 do
  648. resultset^[i]:=
  649. right^.value_set^[i] and left^.value_set^[i];
  650. t:=gensetconstnode(resultset,psetdef(ld));
  651. end;
  652. subn : begin
  653. for i:=0 to 31 do
  654. resultset^[i]:=
  655. left^.value_set^[i] and not(right^.value_set^[i]);
  656. t:=gensetconstnode(resultset,psetdef(ld));
  657. end;
  658. symdifn : begin
  659. for i:=0 to 31 do
  660. resultset^[i]:=
  661. left^.value_set^[i] xor right^.value_set^[i];
  662. t:=gensetconstnode(resultset,psetdef(ld));
  663. end;
  664. unequaln : begin
  665. b:=true;
  666. for i:=0 to 31 do
  667. if right^.value_set^[i]=left^.value_set^[i] then
  668. begin
  669. b:=false;
  670. break;
  671. end;
  672. t:=genordinalconstnode(ord(b),booldef);
  673. end;
  674. equaln : begin
  675. b:=true;
  676. for i:=0 to 31 do
  677. if right^.value_set^[i]<>left^.value_set^[i] then
  678. begin
  679. b:=false;
  680. break;
  681. end;
  682. t:=genordinalconstnode(ord(b),booldef);
  683. end;
  684. {$IfNDef NoSetInclusion}
  685. lten : Begin
  686. b := true;
  687. For i := 0 to 31 Do
  688. If (right^.value_set^[i] And left^.value_set^[i]) <>
  689. left^.value_set^[i] Then
  690. Begin
  691. b := false;
  692. Break
  693. End;
  694. t := genordinalconstnode(ord(b),booldef);
  695. End;
  696. gten : Begin
  697. b := true;
  698. For i := 0 to 31 Do
  699. If (left^.value_set^[i] And right^.value_set^[i]) <>
  700. right^.value_set^[i] Then
  701. Begin
  702. b := false;
  703. Break
  704. End;
  705. t := genordinalconstnode(ord(b),booldef);
  706. End;
  707. {$EndIf NoSetInclusion}
  708. end;
  709. dispose(resultset);
  710. disposetree(p);
  711. p:=t;
  712. firstpass(p);
  713. exit;
  714. end
  715. else
  716. if psetdef(ld)^.settype=smallset then
  717. begin
  718. { are we adding set elements ? }
  719. if right^.treetype=setelementn then
  720. calcregisters(p,2,0,0)
  721. else
  722. calcregisters(p,1,0,0);
  723. location.loc:=LOC_REGISTER;
  724. end
  725. else
  726. begin
  727. calcregisters(p,0,0,0);
  728. { here we call SET... }
  729. procinfo^.flags:=procinfo^.flags or pi_do_call;
  730. location.loc:=LOC_MEM;
  731. end;
  732. convdone:=true;
  733. end
  734. else
  735. { compare pchar to char arrays by addresses
  736. like BP/Delphi }
  737. if (is_pchar(ld) and is_chararray(rd)) or
  738. (is_pchar(rd) and is_chararray(ld)) then
  739. begin
  740. if is_chararray(rd) then
  741. begin
  742. right:=gentypeconvnode(right,ld);
  743. firstpass(right);
  744. end
  745. else
  746. begin
  747. left:=gentypeconvnode(left,rd);
  748. firstpass(left);
  749. end;
  750. location.loc:=LOC_REGISTER;
  751. calcregisters(p,1,0,0);
  752. convdone:=true;
  753. end
  754. else
  755. { is one of the operands a string?,
  756. chararrays are also handled as strings (after conversion) }
  757. if (rd^.deftype=stringdef) or (ld^.deftype=stringdef) or
  758. ((is_chararray(rd) or is_char(rd)) and
  759. (is_chararray(ld) or is_char(ld))) then
  760. begin
  761. if is_widestring(rd) or is_widestring(ld) then
  762. begin
  763. if not(is_widestring(rd)) then
  764. right:=gentypeconvnode(right,cwidestringdef);
  765. if not(is_widestring(ld)) then
  766. left:=gentypeconvnode(left,cwidestringdef);
  767. resulttype:=cwidestringdef;
  768. { this is only for add, the comparisaion is handled later }
  769. location.loc:=LOC_REGISTER;
  770. end
  771. else if is_ansistring(rd) or is_ansistring(ld) then
  772. begin
  773. if not(is_ansistring(rd)) then
  774. right:=gentypeconvnode(right,cansistringdef);
  775. if not(is_ansistring(ld)) then
  776. left:=gentypeconvnode(left,cansistringdef);
  777. { we use ansistrings so no fast exit here }
  778. procinfo^.no_fast_exit:=true;
  779. resulttype:=cansistringdef;
  780. { this is only for add, the comparisaion is handled later }
  781. location.loc:=LOC_REGISTER;
  782. end
  783. else if is_longstring(rd) or is_longstring(ld) then
  784. begin
  785. if not(is_longstring(rd)) then
  786. right:=gentypeconvnode(right,clongstringdef);
  787. if not(is_longstring(ld)) then
  788. left:=gentypeconvnode(left,clongstringdef);
  789. resulttype:=clongstringdef;
  790. { this is only for add, the comparisaion is handled later }
  791. location.loc:=LOC_MEM;
  792. end
  793. else
  794. begin
  795. if not(is_shortstring(rd))
  796. {$ifdef newoptimizations2}
  797. {$ifdef i386}
  798. { shortstring + char handled seperately (JM) }
  799. and (not(cs_optimize in aktglobalswitches) or
  800. (treetype <> addn) or not(is_char(rd)))
  801. {$endif i386}
  802. {$endif newoptimizations2}
  803. then
  804. right:=gentypeconvnode(right,cshortstringdef);
  805. if not(is_shortstring(ld)) then
  806. left:=gentypeconvnode(left,cshortstringdef);
  807. resulttype:=cshortstringdef;
  808. { this is only for add, the comparisaion is handled later }
  809. location.loc:=LOC_MEM;
  810. end;
  811. { only if there is a type cast we need to do again }
  812. { the first pass }
  813. if left^.treetype=typeconvn then
  814. firstpass(left);
  815. if right^.treetype=typeconvn then
  816. firstpass(right);
  817. { here we call STRCONCAT or STRCMP or STRCOPY }
  818. procinfo^.flags:=procinfo^.flags or pi_do_call;
  819. if location.loc=LOC_MEM then
  820. calcregisters(p,0,0,0)
  821. else
  822. calcregisters(p,1,0,0);
  823. {$ifdef i386}
  824. { not always necessary, only if it is not a constant char and }
  825. { not a regvar, but don't know how to check this here (JM) }
  826. if is_char(rd) then
  827. inc(registers32);
  828. {$endif i386}
  829. convdone:=true;
  830. end
  831. else
  832. { is one a real float ? }
  833. if (rd^.deftype=floatdef) or (ld^.deftype=floatdef) then
  834. begin
  835. { if one is a fixed, then convert to f32bit }
  836. if ((rd^.deftype=floatdef) and (pfloatdef(rd)^.typ=f32bit)) or
  837. ((ld^.deftype=floatdef) and (pfloatdef(ld)^.typ=f32bit)) then
  838. begin
  839. if not is_integer(rd) or (treetype<>muln) then
  840. right:=gentypeconvnode(right,s32fixeddef);
  841. if not is_integer(ld) or (treetype<>muln) then
  842. left:=gentypeconvnode(left,s32fixeddef);
  843. firstpass(left);
  844. firstpass(right);
  845. calcregisters(p,1,0,0);
  846. location.loc:=LOC_REGISTER;
  847. end
  848. else
  849. { convert both to bestreal }
  850. begin
  851. right:=gentypeconvnode(right,bestrealdef^);
  852. left:=gentypeconvnode(left,bestrealdef^);
  853. firstpass(left);
  854. firstpass(right);
  855. calcregisters(p,0,1,0);
  856. location.loc:=LOC_FPU;
  857. end;
  858. convdone:=true;
  859. end
  860. else
  861. { pointer comperation and subtraction }
  862. if (rd^.deftype=pointerdef) and (ld^.deftype=pointerdef) then
  863. begin
  864. location.loc:=LOC_REGISTER;
  865. { right:=gentypeconvnode(right,ld); }
  866. { firstpass(right); }
  867. calcregisters(p,1,0,0);
  868. case treetype of
  869. equaln,unequaln :
  870. begin
  871. if is_equal(right^.resulttype,voidpointerdef) then
  872. begin
  873. right:=gentypeconvnode(right,ld);
  874. firstpass(right);
  875. end
  876. else if is_equal(left^.resulttype,voidpointerdef) then
  877. begin
  878. left:=gentypeconvnode(left,rd);
  879. firstpass(left);
  880. end
  881. else if not(is_equal(ld,rd)) then
  882. CGMessage(type_e_mismatch);
  883. end;
  884. ltn,lten,gtn,gten:
  885. begin
  886. if is_equal(right^.resulttype,voidpointerdef) then
  887. begin
  888. right:=gentypeconvnode(right,ld);
  889. firstpass(right);
  890. end
  891. else if is_equal(left^.resulttype,voidpointerdef) then
  892. begin
  893. left:=gentypeconvnode(left,rd);
  894. firstpass(left);
  895. end
  896. else if not(is_equal(ld,rd)) then
  897. CGMessage(type_e_mismatch);
  898. if not(cs_extsyntax in aktmoduleswitches) then
  899. CGMessage(type_e_mismatch);
  900. end;
  901. subn:
  902. begin
  903. if not(is_equal(ld,rd)) then
  904. CGMessage(type_e_mismatch);
  905. if not(cs_extsyntax in aktmoduleswitches) then
  906. CGMessage(type_e_mismatch);
  907. resulttype:=s32bitdef;
  908. exit;
  909. end;
  910. else CGMessage(type_e_mismatch);
  911. end;
  912. convdone:=true;
  913. end
  914. else
  915. if (rd^.deftype=objectdef) and (ld^.deftype=objectdef) and
  916. pobjectdef(rd)^.is_class and pobjectdef(ld)^.is_class then
  917. begin
  918. location.loc:=LOC_REGISTER;
  919. if pobjectdef(rd)^.is_related(pobjectdef(ld)) then
  920. right:=gentypeconvnode(right,ld)
  921. else
  922. left:=gentypeconvnode(left,rd);
  923. firstpass(right);
  924. firstpass(left);
  925. calcregisters(p,1,0,0);
  926. case treetype of
  927. equaln,unequaln : ;
  928. else CGMessage(type_e_mismatch);
  929. end;
  930. convdone:=true;
  931. end
  932. else
  933. if (rd^.deftype=classrefdef) and (ld^.deftype=classrefdef) then
  934. begin
  935. location.loc:=LOC_REGISTER;
  936. if pobjectdef(pclassrefdef(rd)^.pointertype.def)^.is_related(pobjectdef(
  937. pclassrefdef(ld)^.pointertype.def)) then
  938. right:=gentypeconvnode(right,ld)
  939. else
  940. left:=gentypeconvnode(left,rd);
  941. firstpass(right);
  942. firstpass(left);
  943. calcregisters(p,1,0,0);
  944. case treetype of
  945. equaln,unequaln : ;
  946. else CGMessage(type_e_mismatch);
  947. end;
  948. convdone:=true;
  949. end
  950. else
  951. { allows comperasion with nil pointer }
  952. if (rd^.deftype=objectdef) and
  953. pobjectdef(rd)^.is_class then
  954. begin
  955. location.loc:=LOC_REGISTER;
  956. left:=gentypeconvnode(left,rd);
  957. firstpass(left);
  958. calcregisters(p,1,0,0);
  959. case treetype of
  960. equaln,unequaln : ;
  961. else CGMessage(type_e_mismatch);
  962. end;
  963. convdone:=true;
  964. end
  965. else
  966. if (ld^.deftype=objectdef) and
  967. pobjectdef(ld)^.is_class then
  968. begin
  969. location.loc:=LOC_REGISTER;
  970. right:=gentypeconvnode(right,ld);
  971. firstpass(right);
  972. calcregisters(p,1,0,0);
  973. case treetype of
  974. equaln,unequaln : ;
  975. else CGMessage(type_e_mismatch);
  976. end;
  977. convdone:=true;
  978. end
  979. else
  980. if (rd^.deftype=classrefdef) then
  981. begin
  982. left:=gentypeconvnode(left,rd);
  983. firstpass(left);
  984. calcregisters(p,1,0,0);
  985. case treetype of
  986. equaln,unequaln : ;
  987. else CGMessage(type_e_mismatch);
  988. end;
  989. convdone:=true;
  990. end
  991. else
  992. if (ld^.deftype=classrefdef) then
  993. begin
  994. right:=gentypeconvnode(right,ld);
  995. firstpass(right);
  996. calcregisters(p,1,0,0);
  997. case treetype of
  998. equaln,unequaln : ;
  999. else
  1000. CGMessage(type_e_mismatch);
  1001. end;
  1002. convdone:=true;
  1003. end
  1004. else
  1005. { support procvar=nil,procvar<>nil }
  1006. if ((ld^.deftype=procvardef) and (rt=niln)) or
  1007. ((rd^.deftype=procvardef) and (lt=niln)) then
  1008. begin
  1009. calcregisters(p,1,0,0);
  1010. location.loc:=LOC_REGISTER;
  1011. case treetype of
  1012. equaln,unequaln : ;
  1013. else
  1014. CGMessage(type_e_mismatch);
  1015. end;
  1016. convdone:=true;
  1017. end
  1018. else
  1019. {$ifdef SUPPORT_MMX}
  1020. if (cs_mmx in aktlocalswitches) and is_mmx_able_array(ld) and
  1021. is_mmx_able_array(rd) and is_equal(ld,rd) then
  1022. begin
  1023. firstpass(right);
  1024. firstpass(left);
  1025. case treetype of
  1026. addn,subn,xorn,orn,andn:
  1027. ;
  1028. { mul is a little bit restricted }
  1029. muln:
  1030. if not(mmx_type(left^.resulttype) in
  1031. [mmxu16bit,mmxs16bit,mmxfixed16]) then
  1032. CGMessage(type_e_mismatch);
  1033. else
  1034. CGMessage(type_e_mismatch);
  1035. end;
  1036. location.loc:=LOC_MMXREGISTER;
  1037. calcregisters(p,0,0,1);
  1038. convdone:=true;
  1039. end
  1040. else
  1041. {$endif SUPPORT_MMX}
  1042. { this is a little bit dangerous, also the left type }
  1043. { should be checked! This broke the mmx support }
  1044. if (rd^.deftype=pointerdef) or
  1045. is_zero_based_array(rd) then
  1046. begin
  1047. if is_zero_based_array(rd) then
  1048. begin
  1049. resulttype:=new(ppointerdef,init(parraydef(rd)^.elementtype));
  1050. right:=gentypeconvnode(right,resulttype);
  1051. firstpass(right);
  1052. end;
  1053. location.loc:=LOC_REGISTER;
  1054. left:=gentypeconvnode(left,s32bitdef);
  1055. firstpass(left);
  1056. calcregisters(p,1,0,0);
  1057. if treetype=addn then
  1058. begin
  1059. if not(cs_extsyntax in aktmoduleswitches) or
  1060. (not(is_pchar(ld)) and not(m_add_pointer in aktmodeswitches)) then
  1061. CGMessage(type_e_mismatch);
  1062. { Dirty hack, to support multiple firstpasses (PFV) }
  1063. if (resulttype=nil) and
  1064. (rd^.deftype=pointerdef) and
  1065. (ppointerdef(rd)^.pointertype.def^.size>1) then
  1066. begin
  1067. left:=gennode(muln,left,genordinalconstnode(ppointerdef(rd)^.pointertype.def^.size,s32bitdef));
  1068. firstpass(left);
  1069. end;
  1070. end
  1071. else
  1072. CGMessage(type_e_mismatch);
  1073. convdone:=true;
  1074. end
  1075. else
  1076. if (ld^.deftype=pointerdef) or
  1077. is_zero_based_array(ld) then
  1078. begin
  1079. if is_zero_based_array(ld) then
  1080. begin
  1081. resulttype:=new(ppointerdef,init(parraydef(ld)^.elementtype));
  1082. left:=gentypeconvnode(left,resulttype);
  1083. firstpass(left);
  1084. end;
  1085. location.loc:=LOC_REGISTER;
  1086. right:=gentypeconvnode(right,s32bitdef);
  1087. firstpass(right);
  1088. calcregisters(p,1,0,0);
  1089. case treetype of
  1090. addn,subn : begin
  1091. if not(cs_extsyntax in aktmoduleswitches) or
  1092. (not(is_pchar(ld)) and not(m_add_pointer in aktmodeswitches)) then
  1093. CGMessage(type_e_mismatch);
  1094. { Dirty hack, to support multiple firstpasses (PFV) }
  1095. if (resulttype=nil) and
  1096. (ld^.deftype=pointerdef) and
  1097. (ppointerdef(ld)^.pointertype.def^.size>1) then
  1098. begin
  1099. right:=gennode(muln,right,
  1100. genordinalconstnode(ppointerdef(ld)^.pointertype.def^.size,s32bitdef));
  1101. firstpass(right);
  1102. end;
  1103. end;
  1104. else
  1105. CGMessage(type_e_mismatch);
  1106. end;
  1107. convdone:=true;
  1108. end
  1109. else
  1110. if (rd^.deftype=procvardef) and (ld^.deftype=procvardef) and is_equal(rd,ld) then
  1111. begin
  1112. calcregisters(p,1,0,0);
  1113. location.loc:=LOC_REGISTER;
  1114. case treetype of
  1115. equaln,unequaln : ;
  1116. else
  1117. CGMessage(type_e_mismatch);
  1118. end;
  1119. convdone:=true;
  1120. end
  1121. else
  1122. if (ld^.deftype=enumdef) and (rd^.deftype=enumdef) then
  1123. begin
  1124. if not(is_equal(ld,rd)) then
  1125. begin
  1126. right:=gentypeconvnode(right,ld);
  1127. firstpass(right);
  1128. end;
  1129. calcregisters(p,1,0,0);
  1130. case treetype of
  1131. equaln,unequaln,
  1132. ltn,lten,gtn,gten : ;
  1133. else CGMessage(type_e_mismatch);
  1134. end;
  1135. convdone:=true;
  1136. end;
  1137. { the general solution is to convert to 32 bit int }
  1138. if not convdone then
  1139. begin
  1140. { but an int/int gives real/real! }
  1141. if treetype=slashn then
  1142. begin
  1143. CGMessage(type_h_use_div_for_int);
  1144. right:=gentypeconvnode(right,bestrealdef^);
  1145. left:=gentypeconvnode(left,bestrealdef^);
  1146. firstpass(left);
  1147. firstpass(right);
  1148. { maybe we need an integer register to save }
  1149. { a reference }
  1150. if ((left^.location.loc<>LOC_FPU) or
  1151. (right^.location.loc<>LOC_FPU)) and
  1152. (left^.registers32=right^.registers32) then
  1153. calcregisters(p,1,1,0)
  1154. else
  1155. calcregisters(p,0,1,0);
  1156. location.loc:=LOC_FPU;
  1157. end
  1158. else
  1159. begin
  1160. right:=gentypeconvnode(right,s32bitdef);
  1161. left:=gentypeconvnode(left,s32bitdef);
  1162. firstpass(left);
  1163. firstpass(right);
  1164. calcregisters(p,1,0,0);
  1165. location.loc:=LOC_REGISTER;
  1166. end;
  1167. end;
  1168. if codegenerror then
  1169. exit;
  1170. { determines result type for comparions }
  1171. { here the is a problem with multiple passes }
  1172. { example length(s)+1 gets internal 'longint' type first }
  1173. { if it is a arg it is converted to 'LONGINT' }
  1174. { but a second first pass will reset this to 'longint' }
  1175. case treetype of
  1176. ltn,lten,gtn,gten,equaln,unequaln:
  1177. begin
  1178. if (not assigned(resulttype)) or
  1179. (resulttype^.deftype=stringdef) then
  1180. resulttype:=booldef;
  1181. if is_64bitint(left^.resulttype) then
  1182. location.loc:=LOC_JUMP
  1183. else
  1184. location.loc:=LOC_FLAGS;
  1185. end;
  1186. xorn:
  1187. begin
  1188. if not assigned(resulttype) then
  1189. resulttype:=left^.resulttype;
  1190. location.loc:=LOC_REGISTER;
  1191. end;
  1192. addn:
  1193. begin
  1194. if not assigned(resulttype) then
  1195. begin
  1196. { for strings, return is always a 255 char string }
  1197. if is_shortstring(left^.resulttype) then
  1198. resulttype:=cshortstringdef
  1199. else
  1200. resulttype:=left^.resulttype;
  1201. end;
  1202. end;
  1203. {$ifdef cardinalmulfix}
  1204. muln:
  1205. { if we multiply an unsigned with a signed number, the result is signed }
  1206. { in the other cases, the result remains signed or unsigned depending on }
  1207. { the multiplication factors (JM) }
  1208. if (left^.resulttype^.deftype = orddef) and
  1209. (right^.resulttype^.deftype = orddef) and
  1210. is_signed(right^.resulttype) then
  1211. resulttype := right^.resulttype
  1212. else resulttype := left^.resulttype;
  1213. (*
  1214. subn:
  1215. { if we substract a u32bit from a positive constant, the result becomes }
  1216. { s32bit as well (JM) }
  1217. begin
  1218. if (right^.resulttype^.deftype = orddef) and
  1219. (left^.resulttype^.deftype = orddef) and
  1220. (porddef(right^.resulttype)^.typ = u32bit) and
  1221. is_constintnode(left) and
  1222. { (porddef(left^.resulttype)^.typ <> u32bit) and}
  1223. (left^.value > 0) then
  1224. begin
  1225. left := gentypeconvnode(left,u32bitdef);
  1226. firstpass(left);
  1227. end;
  1228. resulttype:=left^.resulttype;
  1229. end;
  1230. *)
  1231. {$endif cardinalmulfix}
  1232. else
  1233. resulttype:=left^.resulttype;
  1234. end;
  1235. end;
  1236. begin
  1237. caddnode:=taddnode;
  1238. end.
  1239. {
  1240. $Log$
  1241. Revision 1.2 2000-08-29 08:24:45 jonas
  1242. * some modifications to -dcardinalmulfix code
  1243. Revision 1.1 2000/08/26 12:24:20 florian
  1244. * initial release
  1245. }