Initial revision
[AROS-Contrib.git] / development / compilers / freepascal / compiler / tcadd.pas
blob9fca255c23d14e6f30de4fa9b3f8c4acd00ea5bf
2 $Id$
3 Copyright (c) 1998-2000 by Florian Klaempfl
5 Type checking and register allocation for add node
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 ****************************************************************************
23 unit tcadd;
24 interface
26 uses
27 tree;
29 procedure firstadd(var p : ptree);
30 function isbinaryoverloaded(var p : ptree) : boolean;
33 implementation
35 uses
36 globtype,systems,tokens,
37 cobjects,verbose,globals,
38 symconst,symtable,aasm,types,
39 {$ifdef newcg}
40 cgbase,
41 {$else newcg}
42 hcodegen,
43 {$endif newcg}
44 htypechk,pass_1,
45 cpubase,tccnv
48 function isbinaryoverloaded(var p : ptree) : boolean;
50 var
51 rd,ld : pdef;
52 t : ptree;
53 optoken : ttoken;
55 begin
56 isbinaryoverloaded:=false;
57 { overloaded operator ? }
58 { load easier access variables }
59 rd:=p^.right^.resulttype;
60 ld:=p^.left^.resulttype;
61 if isbinaryoperatoroverloadable(ld,rd,voiddef,p^.treetype) then
62 begin
63 isbinaryoverloaded:=true;
64 {!!!!!!!!! handle paras }
65 case p^.treetype of
66 { the nil as symtable signs firstcalln that this is
67 an overloaded operator }
68 addn:
69 optoken:=_PLUS;
70 subn:
71 optoken:=_MINUS;
72 muln:
73 optoken:=_STAR;
74 starstarn:
75 optoken:=_STARSTAR;
76 slashn:
77 optoken:=_SLASH;
78 ltn:
79 optoken:=tokens._lt;
80 gtn:
81 optoken:=tokens._gt;
82 lten:
83 optoken:=_lte;
84 gten:
85 optoken:=_gte;
86 equaln,unequaln :
87 optoken:=_EQUAL;
88 symdifn :
89 optoken:=_SYMDIF;
90 modn :
91 optoken:=_OP_MOD;
92 orn :
93 optoken:=_OP_OR;
94 xorn :
95 optoken:=_OP_XOR;
96 andn :
97 optoken:=_OP_AND;
98 divn :
99 optoken:=_OP_DIV;
100 shln :
101 optoken:=_OP_SHL;
102 shrn :
103 optoken:=_OP_SHR;
104 else
105 exit;
106 end;
107 t:=gencallnode(overloaded_operators[optoken],nil);
108 { we have to convert p^.left and p^.right into
109 callparanodes }
110 if t^.symtableprocentry=nil then
111 begin
112 CGMessage(parser_e_operator_not_overloaded);
113 putnode(t);
115 else
116 begin
117 inc(t^.symtableprocentry^.refs);
118 t^.left:=gencallparanode(p^.left,nil);
119 t^.left:=gencallparanode(p^.right,t^.left);
120 if p^.treetype=unequaln then
121 t:=gensinglenode(notn,t);
122 firstpass(t);
123 putnode(p);
124 p:=t;
125 end;
126 end;
127 end;
129 {*****************************************************************************
130 FirstAdd
131 *****************************************************************************}
133 {$ifdef fpc}
134 {$maxfpuregisters 0}
135 {$endif fpc}
137 procedure firstadd(var p : ptree);
139 procedure make_bool_equal_size(var p:ptree);
140 begin
141 if porddef(p^.left^.resulttype)^.typ>porddef(p^.right^.resulttype)^.typ then
142 begin
143 p^.right:=gentypeconvnode(p^.right,porddef(p^.left^.resulttype));
144 p^.right^.convtyp:=tc_bool_2_int;
145 p^.right^.explizit:=true;
146 firstpass(p^.right);
148 else
149 if porddef(p^.left^.resulttype)^.typ<porddef(p^.right^.resulttype)^.typ then
150 begin
151 p^.left:=gentypeconvnode(p^.left,porddef(p^.right^.resulttype));
152 p^.left^.convtyp:=tc_bool_2_int;
153 p^.left^.explizit:=true;
154 firstpass(p^.left);
155 end;
156 end;
159 t,hp : ptree;
161 lt,rt,pt: ttreetyp;
162 rv,lv : longint;
163 rvd,lvd : bestreal;
164 resdef,
165 rd,ld : pdef;
166 tempdef : pdef;
167 concatstrings : boolean;
169 { to evalute const sets }
170 resultset : pconstset;
171 i : longint;
172 b : boolean;
173 convdone : boolean;
174 s1,s2 : pchar;
175 l1,l2 : longint;
177 begin
178 { first do the two subtrees }
179 firstpass(p^.left);
180 firstpass(p^.right);
181 if codegenerror then
182 exit;
184 { convert array constructors to sets, because there is no other operator
185 possible for array constructors }
186 if is_array_constructor(p^.left^.resulttype) then
187 begin
188 arrayconstructor_to_set(p^.left);
189 firstpass(p^.left);
190 end;
191 if is_array_constructor(p^.right^.resulttype) then
192 begin
193 arrayconstructor_to_set(p^.right);
194 firstpass(p^.right);
195 end;
196 { both left and right need to be valid }
197 set_varstate(p^.left,true);
198 set_varstate(p^.right,true);
200 { load easier access variables }
201 lt:=p^.left^.treetype;
202 rt:=p^.right^.treetype;
203 { always use pt instead of p^.treetype, becayse p may be replaced }
204 { with a typeconversion node! (JM) }
205 pt:=p^.treetype;
206 rd:=p^.right^.resulttype;
207 ld:=p^.left^.resulttype;
208 convdone:=false;
210 if isbinaryoverloaded(p) then
211 exit;
212 { compact consts }
214 { convert int consts to real consts, if the }
215 { other operand is a real const }
216 if (rt=realconstn) and is_constintnode(p^.left) then
217 begin
218 t:=genrealconstnode(p^.left^.value,p^.right^.resulttype);
219 disposetree(p^.left);
220 p^.left:=t;
221 lt:=realconstn;
222 end;
223 if (lt=realconstn) and is_constintnode(p^.right) then
224 begin
225 t:=genrealconstnode(p^.right^.value,p^.left^.resulttype);
226 disposetree(p^.right);
227 p^.right:=t;
228 rt:=realconstn;
229 end;
231 { both are int constants, also allow operations on two equal enums
232 in fpc mode (Needed for conversion of C code) }
233 if ((lt=ordconstn) and (rt=ordconstn)) and
234 ((is_constintnode(p^.left) and is_constintnode(p^.right)) or
235 (is_constboolnode(p^.left) and is_constboolnode(p^.right) and
236 (pt in [ltn,lten,gtn,gten,equaln,unequaln,andn,xorn,orn]))) then
237 begin
238 { return a boolean for boolean operations (and,xor,or) }
239 if is_constboolnode(p^.left) then
240 resdef:=booldef
241 else
242 resdef:=s32bitdef;
243 lv:=p^.left^.value;
244 rv:=p^.right^.value;
245 case pt of
246 addn : t:=genordinalconstnode(lv+rv,resdef);
247 subn : t:=genordinalconstnode(lv-rv,resdef);
248 muln : t:=genordinalconstnode(lv*rv,resdef);
249 xorn : t:=genordinalconstnode(lv xor rv,resdef);
250 orn : t:=genordinalconstnode(lv or rv,resdef);
251 andn : t:=genordinalconstnode(lv and rv,resdef);
252 ltn : t:=genordinalconstnode(ord(lv<rv),booldef);
253 lten : t:=genordinalconstnode(ord(lv<=rv),booldef);
254 gtn : t:=genordinalconstnode(ord(lv>rv),booldef);
255 gten : t:=genordinalconstnode(ord(lv>=rv),booldef);
256 equaln : t:=genordinalconstnode(ord(lv=rv),booldef);
257 unequaln : t:=genordinalconstnode(ord(lv<>rv),booldef);
258 slashn : begin
259 { int/int becomes a real }
260 if int(rv)=0 then
261 begin
262 Message(parser_e_invalid_float_operation);
263 t:=genrealconstnode(0,bestrealdef^);
265 else
266 t:=genrealconstnode(int(lv)/int(rv),bestrealdef^);
267 firstpass(t);
268 end;
269 else
270 CGMessage(type_e_mismatch);
271 end;
272 disposetree(p);
273 firstpass(t);
274 p:=t;
275 exit;
276 end;
278 { both real constants ? }
279 if (lt=realconstn) and (rt=realconstn) then
280 begin
281 lvd:=p^.left^.value_real;
282 rvd:=p^.right^.value_real;
283 case pt of
284 addn : t:=genrealconstnode(lvd+rvd,bestrealdef^);
285 subn : t:=genrealconstnode(lvd-rvd,bestrealdef^);
286 muln : t:=genrealconstnode(lvd*rvd,bestrealdef^);
287 starstarn,
288 caretn : begin
289 if lvd<0 then
290 begin
291 Message(parser_e_invalid_float_operation);
292 t:=genrealconstnode(0,bestrealdef^);
294 else if lvd=0 then
295 t:=genrealconstnode(1.0,bestrealdef^)
296 else
297 t:=genrealconstnode(exp(ln(lvd)*rvd),bestrealdef^);
298 end;
299 slashn :
300 begin
301 if rvd=0 then
302 begin
303 Message(parser_e_invalid_float_operation);
304 t:=genrealconstnode(0,bestrealdef^);
306 else
307 t:=genrealconstnode(lvd/rvd,bestrealdef^);
308 end;
309 ltn : t:=genordinalconstnode(ord(lvd<rvd),booldef);
310 lten : t:=genordinalconstnode(ord(lvd<=rvd),booldef);
311 gtn : t:=genordinalconstnode(ord(lvd>rvd),booldef);
312 gten : t:=genordinalconstnode(ord(lvd>=rvd),booldef);
313 equaln : t:=genordinalconstnode(ord(lvd=rvd),booldef);
314 unequaln : t:=genordinalconstnode(ord(lvd<>rvd),booldef);
315 else
316 CGMessage(type_e_mismatch);
317 end;
318 disposetree(p);
319 p:=t;
320 firstpass(p);
321 exit;
322 end;
324 { concating strings ? }
325 concatstrings:=false;
326 s1:=nil;
327 s2:=nil;
328 if (lt=ordconstn) and (rt=ordconstn) and
329 is_char(ld) and is_char(rd) then
330 begin
331 s1:=strpnew(char(byte(p^.left^.value)));
332 s2:=strpnew(char(byte(p^.right^.value)));
333 l1:=1;
334 l2:=1;
335 concatstrings:=true;
337 else
338 if (lt=stringconstn) and (rt=ordconstn) and is_char(rd) then
339 begin
340 s1:=getpcharcopy(p^.left);
341 l1:=p^.left^.length;
342 s2:=strpnew(char(byte(p^.right^.value)));
343 l2:=1;
344 concatstrings:=true;
346 else
347 if (lt=ordconstn) and (rt=stringconstn) and is_char(ld) then
348 begin
349 s1:=strpnew(char(byte(p^.left^.value)));
350 l1:=1;
351 s2:=getpcharcopy(p^.right);
352 l2:=p^.right^.length;
353 concatstrings:=true;
355 else if (lt=stringconstn) and (rt=stringconstn) then
356 begin
357 s1:=getpcharcopy(p^.left);
358 l1:=p^.left^.length;
359 s2:=getpcharcopy(p^.right);
360 l2:=p^.right^.length;
361 concatstrings:=true;
362 end;
364 { I will need to translate all this to ansistrings !!! }
365 if concatstrings then
366 begin
367 case pt of
368 addn :
369 t:=genpcharconstnode(concatansistrings(s1,s2,l1,l2),l1+l2);
370 ltn :
371 t:=genordinalconstnode(byte(compareansistrings(s1,s2,l1,l2)<0),booldef);
372 lten :
373 t:=genordinalconstnode(byte(compareansistrings(s1,s2,l1,l2)<=0),booldef);
374 gtn :
375 t:=genordinalconstnode(byte(compareansistrings(s1,s2,l1,l2)>0),booldef);
376 gten :
377 t:=genordinalconstnode(byte(compareansistrings(s1,s2,l1,l2)>=0),booldef);
378 equaln :
379 t:=genordinalconstnode(byte(compareansistrings(s1,s2,l1,l2)=0),booldef);
380 unequaln :
381 t:=genordinalconstnode(byte(compareansistrings(s1,s2,l1,l2)<>0),booldef);
382 end;
383 ansistringdispose(s1,l1);
384 ansistringdispose(s2,l2);
385 disposetree(p);
386 firstpass(t);
387 p:=t;
388 exit;
389 end;
391 { if both are orddefs then check sub types }
392 if (ld^.deftype=orddef) and (rd^.deftype=orddef) then
393 begin
394 { 2 booleans ? }
395 if is_boolean(ld) and is_boolean(rd) then
396 begin
397 case pt of
398 andn,
399 orn:
400 begin
401 make_bool_equal_size(p);
402 calcregisters(p,0,0,0);
403 p^.location.loc:=LOC_JUMP;
404 end;
405 xorn,ltn,lten,gtn,gten:
406 begin
407 make_bool_equal_size(p);
408 if (p^.left^.location.loc in [LOC_JUMP,LOC_FLAGS]) and
409 (p^.left^.location.loc in [LOC_JUMP,LOC_FLAGS]) then
410 calcregisters(p,2,0,0)
411 else
412 calcregisters(p,1,0,0);
413 end;
414 unequaln,
415 equaln:
416 begin
417 make_bool_equal_size(p);
418 { Remove any compares with constants }
419 if (p^.left^.treetype=ordconstn) then
420 begin
421 hp:=p^.right;
422 b:=(p^.left^.value<>0);
423 ot:=pt;
424 disposetree(p^.left);
425 putnode(p);
426 p:=hp;
427 if (not(b) and (ot=equaln)) or
428 (b and (ot=unequaln)) then
429 begin
430 p:=gensinglenode(notn,p);
431 firstpass(p);
432 end;
433 exit;
434 end;
435 if (p^.right^.treetype=ordconstn) then
436 begin
437 hp:=p^.left;
438 b:=(p^.right^.value<>0);
439 ot:=pt;
440 disposetree(p^.right);
441 putnode(p);
442 p:=hp;
443 if (not(b) and (ot=equaln)) or
444 (b and (ot=unequaln)) then
445 begin
446 p:=gensinglenode(notn,p);
447 firstpass(p);
448 end;
449 exit;
450 end;
451 if (p^.left^.location.loc in [LOC_JUMP,LOC_FLAGS]) and
452 (p^.left^.location.loc in [LOC_JUMP,LOC_FLAGS]) then
453 calcregisters(p,2,0,0)
454 else
455 calcregisters(p,1,0,0);
456 end;
457 else
458 CGMessage(type_e_mismatch);
459 end;
461 { these one can't be in flags! }
463 Yes they can, secondadd converts the loc_flags to a register.
464 The typeconversions below are simply removed by firsttypeconv()
465 because the resulttype of p^.left = p^.left^.resulttype
466 (surprise! :) (JM)
468 if pt in [xorn,unequaln,equaln] then
469 begin
470 if p^.left^.location.loc=LOC_FLAGS then
471 begin
472 p^.left:=gentypeconvnode(p^.left,porddef(p^.left^.resulttype));
473 p^.left^.convtyp:=tc_bool_2_int;
474 p^.left^.explizit:=true;
475 firstpass(p^.left);
476 end;
477 if p^.right^.location.loc=LOC_FLAGS then
478 begin
479 p^.right:=gentypeconvnode(p^.right,porddef(p^.right^.resulttype));
480 p^.right^.convtyp:=tc_bool_2_int;
481 p^.right^.explizit:=true;
482 firstpass(p^.right);
483 end;
484 { readjust registers }
485 calcregisters(p,1,0,0);
486 end;
488 convdone:=true;
490 else
491 { Both are chars? only convert to shortstrings for addn }
492 if is_char(rd) and is_char(ld) then
493 begin
494 if pt=addn then
495 begin
496 p^.left:=gentypeconvnode(p^.left,cshortstringdef);
497 p^.right:=gentypeconvnode(p^.right,cshortstringdef);
498 firstpass(p^.left);
499 firstpass(p^.right);
500 { here we call STRCOPY }
501 procinfo^.flags:=procinfo^.flags or pi_do_call;
502 calcregisters(p,0,0,0);
503 p^.location.loc:=LOC_MEM;
505 else
506 calcregisters(p,1,0,0);
507 convdone:=true;
509 { is there a 64 bit type ? }
510 else if ((porddef(rd)^.typ=s64bit) or (porddef(ld)^.typ=s64bit)) and
511 { the / operator is handled later }
512 (pt<>slashn) then
513 begin
514 if (porddef(ld)^.typ<>s64bit) then
515 begin
516 p^.left:=gentypeconvnode(p^.left,cs64bitdef);
517 firstpass(p^.left);
518 end;
519 if (porddef(rd)^.typ<>s64bit) then
520 begin
521 p^.right:=gentypeconvnode(p^.right,cs64bitdef);
522 firstpass(p^.right);
523 end;
524 calcregisters(p,2,0,0);
525 convdone:=true;
527 else if ((porddef(rd)^.typ=u64bit) or (porddef(ld)^.typ=u64bit)) and
528 { the / operator is handled later }
529 (pt<>slashn) then
530 begin
531 if (porddef(ld)^.typ<>u64bit) then
532 begin
533 p^.left:=gentypeconvnode(p^.left,cu64bitdef);
534 firstpass(p^.left);
535 end;
536 if (porddef(rd)^.typ<>u64bit) then
537 begin
538 p^.right:=gentypeconvnode(p^.right,cu64bitdef);
539 firstpass(p^.right);
540 end;
541 calcregisters(p,2,0,0);
542 convdone:=true;
544 else
545 { is there a cardinal? }
546 if ((porddef(rd)^.typ=u32bit) or (porddef(ld)^.typ=u32bit)) and
547 { the / operator is handled later }
548 (pt<>slashn) then
549 begin
550 if is_signed(ld) and
551 { then rd = u32bit }
552 { convert positive constants to u32bit }
553 not(is_constintnode(p^.left) and
554 (p^.left^.value >= 0)) and
555 { range/overflow checking on mixed signed/cardinal expressions }
556 { is only possible if you convert everything to 64bit (JM) }
557 ((aktlocalswitches * [cs_check_overflow,cs_check_range] <> []) and
558 (pt in [addn,subn,muln])) then
559 begin
560 { perform the operation in 64bit }
561 CGMessage(type_w_mixed_signed_unsigned);
562 p^.left := gentypeconvnode(p^.left,cs64bitdef);
563 firstpass(p^.left);
564 p^.right := gentypeconvnode(p^.right,cs64bitdef);
565 firstpass(p^.right);
567 else
568 begin
569 if is_signed(ld) and
570 not(is_constintnode(p^.left) and
571 (p^.left^.value >= 0)) and
572 (cs_check_range in aktlocalswitches) then
573 CGMessage(type_w_mixed_signed_unsigned2);
574 p^.left := gentypeconvnode(p^.left,u32bitdef);
575 firstpass(p^.left);
577 if is_signed(rd) and
578 { then ld = u32bit }
579 { convert positive constants to u32bit }
580 not(is_constintnode(p^.right) and
581 (p^.right^.value >= 0)) and
582 ((aktlocalswitches * [cs_check_overflow,cs_check_range] <> []) and
583 (pt in [addn,subn,muln])) then
584 begin
585 { perform the operation in 64bit }
586 CGMessage(type_w_mixed_signed_unsigned);
587 p^.left := gentypeconvnode(p^.left,cs64bitdef);
588 firstpass(p^.left);
589 p^.right := gentypeconvnode(p^.right,cs64bitdef);
590 firstpass(p^.right);
592 else
593 begin
594 if is_signed(rd) and
595 not(is_constintnode(p^.right) and
596 (p^.right^.value >= 0)) and
597 (cs_check_range in aktlocalswitches) then
598 CGMessage(type_w_mixed_signed_unsigned2);
599 p^.right := gentypeconvnode(p^.right,u32bitdef);
600 firstpass(p^.right);
601 end;
602 end;
603 { did we convert things to 64bit? }
604 if porddef(p^.left^.resulttype)^.typ = s64bit then
605 calcregisters(p,2,0,0)
606 else
607 begin
608 calcregisters(p,1,0,0);
609 { for unsigned mul we need an extra register }
610 if pt=muln then
611 inc(p^.registers32);
612 end;
613 convdone:=true;
614 end;
616 else
618 { left side a setdef, must be before string processing,
619 else array constructor can be seen as array of char (PFV) }
620 if (ld^.deftype=setdef) {or is_array_constructor(ld)} then
621 begin
622 { trying to add a set element? }
623 if (pt=addn) and (rd^.deftype<>setdef) then
624 begin
625 if (rt=setelementn) then
626 begin
627 if not(is_equal(psetdef(ld)^.elementtype.def,rd)) then
628 CGMessage(type_e_set_element_are_not_comp);
630 else
631 CGMessage(type_e_mismatch)
633 else
634 begin
635 if not(pt in [addn,subn,symdifn,muln,equaln,unequaln
636 {$IfNDef NoSetInclusion}
637 ,lten,gten
638 {$EndIf NoSetInclusion}
639 ]) then
640 CGMessage(type_e_set_operation_unknown);
641 { right def must be a also be set }
642 if (rd^.deftype<>setdef) or not(is_equal(rd,ld)) then
643 CGMessage(type_e_set_element_are_not_comp);
644 end;
646 { ranges require normsets }
647 if (psetdef(ld)^.settype=smallset) and
648 (rt=setelementn) and
649 assigned(p^.right^.right) then
650 begin
651 { generate a temporary normset def, it'll be destroyed
652 when the symtable is unloaded }
653 tempdef:=new(psetdef,init(psetdef(ld)^.elementtype.def,255));
654 p^.left:=gentypeconvnode(p^.left,tempdef);
655 firstpass(p^.left);
656 ld:=p^.left^.resulttype;
657 end;
659 { if the destination is not a smallset then insert a typeconv
660 which loads a smallset into a normal set }
661 if (psetdef(ld)^.settype<>smallset) and
662 (psetdef(rd)^.settype=smallset) then
663 begin
664 if (p^.right^.treetype=setconstn) then
665 begin
666 t:=gensetconstnode(p^.right^.value_set,psetdef(p^.left^.resulttype));
667 t^.left:=p^.right^.left;
668 putnode(p^.right);
669 p^.right:=t;
671 else
672 p^.right:=gentypeconvnode(p^.right,psetdef(p^.left^.resulttype));
673 firstpass(p^.right);
674 end;
676 { do constant evaluation }
677 if (p^.right^.treetype=setconstn) and
678 not assigned(p^.right^.left) and
679 (p^.left^.treetype=setconstn) and
680 not assigned(p^.left^.left) then
681 begin
682 new(resultset);
683 case pt of
684 addn : begin
685 for i:=0 to 31 do
686 resultset^[i]:=
687 p^.right^.value_set^[i] or p^.left^.value_set^[i];
688 t:=gensetconstnode(resultset,psetdef(ld));
689 end;
690 muln : begin
691 for i:=0 to 31 do
692 resultset^[i]:=
693 p^.right^.value_set^[i] and p^.left^.value_set^[i];
694 t:=gensetconstnode(resultset,psetdef(ld));
695 end;
696 subn : begin
697 for i:=0 to 31 do
698 resultset^[i]:=
699 p^.left^.value_set^[i] and not(p^.right^.value_set^[i]);
700 t:=gensetconstnode(resultset,psetdef(ld));
701 end;
702 symdifn : begin
703 for i:=0 to 31 do
704 resultset^[i]:=
705 p^.left^.value_set^[i] xor p^.right^.value_set^[i];
706 t:=gensetconstnode(resultset,psetdef(ld));
707 end;
708 unequaln : begin
709 b:=true;
710 for i:=0 to 31 do
711 if p^.right^.value_set^[i]=p^.left^.value_set^[i] then
712 begin
713 b:=false;
714 break;
715 end;
716 t:=genordinalconstnode(ord(b),booldef);
717 end;
718 equaln : begin
719 b:=true;
720 for i:=0 to 31 do
721 if p^.right^.value_set^[i]<>p^.left^.value_set^[i] then
722 begin
723 b:=false;
724 break;
725 end;
726 t:=genordinalconstnode(ord(b),booldef);
727 end;
728 {$IfNDef NoSetInclusion}
729 lten : Begin
730 b := true;
731 For i := 0 to 31 Do
732 If (p^.right^.value_set^[i] And p^.left^.value_set^[i]) <>
733 p^.left^.value_set^[i] Then
734 Begin
735 b := false;
736 Break
737 End;
738 t := genordinalconstnode(ord(b),booldef);
739 End;
740 gten : Begin
741 b := true;
742 For i := 0 to 31 Do
743 If (p^.left^.value_set^[i] And p^.right^.value_set^[i]) <>
744 p^.right^.value_set^[i] Then
745 Begin
746 b := false;
747 Break
748 End;
749 t := genordinalconstnode(ord(b),booldef);
750 End;
751 {$EndIf NoSetInclusion}
752 end;
753 dispose(resultset);
754 disposetree(p);
755 p:=t;
756 firstpass(p);
757 exit;
759 else
760 if psetdef(ld)^.settype=smallset then
761 begin
762 { are we adding set elements ? }
763 if p^.right^.treetype=setelementn then
764 calcregisters(p,2,0,0)
765 else
766 calcregisters(p,1,0,0);
767 p^.location.loc:=LOC_REGISTER;
769 else
770 begin
771 calcregisters(p,0,0,0);
772 { here we call SET... }
773 procinfo^.flags:=procinfo^.flags or pi_do_call;
774 p^.location.loc:=LOC_MEM;
775 end;
776 convdone:=true;
778 else
779 { compare pchar to char arrays by addresses
780 like BP/Delphi }
781 if (is_pchar(ld) and is_chararray(rd)) or
782 (is_pchar(rd) and is_chararray(ld)) then
783 begin
784 if is_chararray(rd) then
785 begin
786 p^.right:=gentypeconvnode(p^.right,ld);
787 firstpass(p^.right);
789 else
790 begin
791 p^.left:=gentypeconvnode(p^.left,rd);
792 firstpass(p^.left);
793 end;
794 p^.location.loc:=LOC_REGISTER;
795 calcregisters(p,1,0,0);
796 convdone:=true;
798 else
799 { is one of the operands a string?,
800 chararrays are also handled as strings (after conversion) }
801 if (rd^.deftype=stringdef) or (ld^.deftype=stringdef) or
802 ((is_chararray(rd) or is_char(rd)) and
803 (is_chararray(ld) or is_char(ld))) then
804 begin
805 if is_widestring(rd) or is_widestring(ld) then
806 begin
807 if not(is_widestring(rd)) then
808 p^.right:=gentypeconvnode(p^.right,cwidestringdef);
809 if not(is_widestring(ld)) then
810 p^.left:=gentypeconvnode(p^.left,cwidestringdef);
811 p^.resulttype:=cwidestringdef;
812 { this is only for add, the comparisaion is handled later }
813 p^.location.loc:=LOC_REGISTER;
815 else if is_ansistring(rd) or is_ansistring(ld) then
816 begin
817 if not(is_ansistring(rd)) then
818 p^.right:=gentypeconvnode(p^.right,cansistringdef);
819 if not(is_ansistring(ld)) then
820 p^.left:=gentypeconvnode(p^.left,cansistringdef);
821 { we use ansistrings so no fast exit here }
822 procinfo^.no_fast_exit:=true;
823 p^.resulttype:=cansistringdef;
824 { this is only for add, the comparisaion is handled later }
825 p^.location.loc:=LOC_REGISTER;
827 else if is_longstring(rd) or is_longstring(ld) then
828 begin
829 if not(is_longstring(rd)) then
830 p^.right:=gentypeconvnode(p^.right,clongstringdef);
831 if not(is_longstring(ld)) then
832 p^.left:=gentypeconvnode(p^.left,clongstringdef);
833 p^.resulttype:=clongstringdef;
834 { this is only for add, the comparisaion is handled later }
835 p^.location.loc:=LOC_MEM;
837 else
838 begin
839 if not(is_shortstring(rd))
840 {$ifdef newoptimizations2}
841 {$ifdef i386}
842 { shortstring + char handled seperately (JM) }
843 and (not(cs_optimize in aktglobalswitches) or
844 (pt <> addn) or not(is_char(rd)))
845 {$endif i386}
846 {$endif newoptimizations2}
847 then
848 p^.right:=gentypeconvnode(p^.right,cshortstringdef);
849 if not(is_shortstring(ld)) then
850 p^.left:=gentypeconvnode(p^.left,cshortstringdef);
851 p^.resulttype:=cshortstringdef;
852 { this is only for add, the comparisaion is handled later }
853 p^.location.loc:=LOC_MEM;
854 end;
855 { only if there is a type cast we need to do again }
856 { the first pass }
857 if p^.left^.treetype=typeconvn then
858 firstpass(p^.left);
859 if p^.right^.treetype=typeconvn then
860 firstpass(p^.right);
861 { here we call STRCONCAT or STRCMP or STRCOPY }
862 procinfo^.flags:=procinfo^.flags or pi_do_call;
863 if p^.location.loc=LOC_MEM then
864 calcregisters(p,0,0,0)
865 else
866 calcregisters(p,1,0,0);
867 {$ifdef newoptimizations}
868 {$ifdef i386}
869 { not always necessary, only if it is not a constant char and }
870 { not a regvar, but don't know how to check this here (JM) }
871 if is_char(rd) then
872 inc(p^.registers32);
873 {$endif i386}
874 {$endif newoptimizations}
875 convdone:=true;
877 else
879 { is one a real float ? }
880 if (rd^.deftype=floatdef) or (ld^.deftype=floatdef) then
881 begin
882 { if one is a fixed, then convert to f32bit }
883 if ((rd^.deftype=floatdef) and (pfloatdef(rd)^.typ=f32bit)) or
884 ((ld^.deftype=floatdef) and (pfloatdef(ld)^.typ=f32bit)) then
885 begin
886 if not is_integer(rd) or (pt<>muln) then
887 p^.right:=gentypeconvnode(p^.right,s32fixeddef);
888 if not is_integer(ld) or (pt<>muln) then
889 p^.left:=gentypeconvnode(p^.left,s32fixeddef);
890 firstpass(p^.left);
891 firstpass(p^.right);
892 calcregisters(p,1,0,0);
893 p^.location.loc:=LOC_REGISTER;
895 else
896 { convert both to bestreal }
897 begin
898 p^.right:=gentypeconvnode(p^.right,bestrealdef^);
899 p^.left:=gentypeconvnode(p^.left,bestrealdef^);
900 firstpass(p^.left);
901 firstpass(p^.right);
902 calcregisters(p,0,1,0);
903 p^.location.loc:=LOC_FPU;
904 end;
905 convdone:=true;
907 else
909 { pointer comperation and subtraction }
910 if (rd^.deftype=pointerdef) and (ld^.deftype=pointerdef) then
911 begin
912 p^.location.loc:=LOC_REGISTER;
913 { p^.right:=gentypeconvnode(p^.right,ld); }
914 { firstpass(p^.right); }
915 calcregisters(p,1,0,0);
916 case pt of
917 equaln,unequaln :
918 begin
919 if is_equal(p^.right^.resulttype,voidpointerdef) then
920 begin
921 p^.right:=gentypeconvnode(p^.right,ld);
922 firstpass(p^.right);
924 else if is_equal(p^.left^.resulttype,voidpointerdef) then
925 begin
926 p^.left:=gentypeconvnode(p^.left,rd);
927 firstpass(p^.left);
929 else if not(is_equal(ld,rd)) then
930 CGMessage(type_e_mismatch);
931 end;
932 ltn,lten,gtn,gten:
933 begin
934 if is_equal(p^.right^.resulttype,voidpointerdef) then
935 begin
936 p^.right:=gentypeconvnode(p^.right,ld);
937 firstpass(p^.right);
939 else if is_equal(p^.left^.resulttype,voidpointerdef) then
940 begin
941 p^.left:=gentypeconvnode(p^.left,rd);
942 firstpass(p^.left);
944 else if not(is_equal(ld,rd)) then
945 CGMessage(type_e_mismatch);
946 if not(cs_extsyntax in aktmoduleswitches) then
947 CGMessage(type_e_mismatch);
948 end;
949 subn:
950 begin
951 if not(is_equal(ld,rd)) then
952 CGMessage(type_e_mismatch);
953 if not(cs_extsyntax in aktmoduleswitches) then
954 CGMessage(type_e_mismatch);
955 p^.resulttype:=s32bitdef;
956 exit;
957 end;
958 else CGMessage(type_e_mismatch);
959 end;
960 convdone:=true;
962 else
964 if (rd^.deftype=objectdef) and (ld^.deftype=objectdef) and
965 pobjectdef(rd)^.is_class and pobjectdef(ld)^.is_class then
966 begin
967 p^.location.loc:=LOC_REGISTER;
968 if pobjectdef(rd)^.is_related(pobjectdef(ld)) then
969 p^.right:=gentypeconvnode(p^.right,ld)
970 else
971 p^.left:=gentypeconvnode(p^.left,rd);
972 firstpass(p^.right);
973 firstpass(p^.left);
974 calcregisters(p,1,0,0);
975 case pt of
976 equaln,unequaln : ;
977 else CGMessage(type_e_mismatch);
978 end;
979 convdone:=true;
981 else
983 if (rd^.deftype=classrefdef) and (ld^.deftype=classrefdef) then
984 begin
985 p^.location.loc:=LOC_REGISTER;
986 if pobjectdef(pclassrefdef(rd)^.pointertype.def)^.is_related(pobjectdef(
987 pclassrefdef(ld)^.pointertype.def)) then
988 p^.right:=gentypeconvnode(p^.right,ld)
989 else
990 p^.left:=gentypeconvnode(p^.left,rd);
991 firstpass(p^.right);
992 firstpass(p^.left);
993 calcregisters(p,1,0,0);
994 case pt of
995 equaln,unequaln : ;
996 else CGMessage(type_e_mismatch);
997 end;
998 convdone:=true;
1000 else
1002 { allows comperasion with nil pointer }
1003 if (rd^.deftype=objectdef) and
1004 pobjectdef(rd)^.is_class then
1005 begin
1006 p^.location.loc:=LOC_REGISTER;
1007 p^.left:=gentypeconvnode(p^.left,rd);
1008 firstpass(p^.left);
1009 calcregisters(p,1,0,0);
1010 case pt of
1011 equaln,unequaln : ;
1012 else CGMessage(type_e_mismatch);
1013 end;
1014 convdone:=true;
1016 else
1018 if (ld^.deftype=objectdef) and
1019 pobjectdef(ld)^.is_class then
1020 begin
1021 p^.location.loc:=LOC_REGISTER;
1022 p^.right:=gentypeconvnode(p^.right,ld);
1023 firstpass(p^.right);
1024 calcregisters(p,1,0,0);
1025 case pt of
1026 equaln,unequaln : ;
1027 else CGMessage(type_e_mismatch);
1028 end;
1029 convdone:=true;
1031 else
1033 if (rd^.deftype=classrefdef) then
1034 begin
1035 p^.left:=gentypeconvnode(p^.left,rd);
1036 firstpass(p^.left);
1037 calcregisters(p,1,0,0);
1038 case pt of
1039 equaln,unequaln : ;
1040 else CGMessage(type_e_mismatch);
1041 end;
1042 convdone:=true;
1044 else
1046 if (ld^.deftype=classrefdef) then
1047 begin
1048 p^.right:=gentypeconvnode(p^.right,ld);
1049 firstpass(p^.right);
1050 calcregisters(p,1,0,0);
1051 case pt of
1052 equaln,unequaln : ;
1053 else
1054 CGMessage(type_e_mismatch);
1055 end;
1056 convdone:=true;
1058 else
1060 { support procvar=nil,procvar<>nil }
1061 if ((ld^.deftype=procvardef) and (rt=niln)) or
1062 ((rd^.deftype=procvardef) and (lt=niln)) then
1063 begin
1064 calcregisters(p,1,0,0);
1065 p^.location.loc:=LOC_REGISTER;
1066 case pt of
1067 equaln,unequaln : ;
1068 else
1069 CGMessage(type_e_mismatch);
1070 end;
1071 convdone:=true;
1073 else
1075 {$ifdef SUPPORT_MMX}
1076 if (cs_mmx in aktlocalswitches) and is_mmx_able_array(ld) and
1077 is_mmx_able_array(rd) and is_equal(ld,rd) then
1078 begin
1079 firstpass(p^.right);
1080 firstpass(p^.left);
1081 case pt of
1082 addn,subn,xorn,orn,andn:
1084 { mul is a little bit restricted }
1085 muln:
1086 if not(mmx_type(p^.left^.resulttype) in
1087 [mmxu16bit,mmxs16bit,mmxfixed16]) then
1088 CGMessage(type_e_mismatch);
1089 else
1090 CGMessage(type_e_mismatch);
1091 end;
1092 p^.location.loc:=LOC_MMXREGISTER;
1093 calcregisters(p,0,0,1);
1094 convdone:=true;
1096 else
1097 {$endif SUPPORT_MMX}
1099 { this is a little bit dangerous, also the left type }
1100 { should be checked! This broke the mmx support }
1101 if (rd^.deftype=pointerdef) or
1102 is_zero_based_array(rd) then
1103 begin
1104 if is_zero_based_array(rd) then
1105 begin
1106 p^.resulttype:=new(ppointerdef,init(parraydef(rd)^.elementtype));
1107 p^.right:=gentypeconvnode(p^.right,p^.resulttype);
1108 firstpass(p^.right);
1109 end;
1110 p^.location.loc:=LOC_REGISTER;
1111 p^.left:=gentypeconvnode(p^.left,s32bitdef);
1112 firstpass(p^.left);
1113 calcregisters(p,1,0,0);
1114 if pt=addn then
1115 begin
1116 if not(cs_extsyntax in aktmoduleswitches) or
1117 (not(is_pchar(ld)) and not(m_add_pointer in aktmodeswitches)) then
1118 CGMessage(type_e_mismatch);
1119 { Dirty hack, to support multiple firstpasses (PFV) }
1120 if (p^.resulttype=nil) and
1121 (rd^.deftype=pointerdef) and
1122 (ppointerdef(rd)^.pointertype.def^.size>1) then
1123 begin
1124 p^.left:=gennode(muln,p^.left,genordinalconstnode(ppointerdef(rd)^.pointertype.def^.size,s32bitdef));
1125 firstpass(p^.left);
1126 end;
1128 else
1129 CGMessage(type_e_mismatch);
1130 convdone:=true;
1132 else
1134 if (ld^.deftype=pointerdef) or
1135 is_zero_based_array(ld) then
1136 begin
1137 if is_zero_based_array(ld) then
1138 begin
1139 p^.resulttype:=new(ppointerdef,init(parraydef(ld)^.elementtype));
1140 p^.left:=gentypeconvnode(p^.left,p^.resulttype);
1141 firstpass(p^.left);
1142 end;
1143 p^.location.loc:=LOC_REGISTER;
1144 p^.right:=gentypeconvnode(p^.right,s32bitdef);
1145 firstpass(p^.right);
1146 calcregisters(p,1,0,0);
1147 case pt of
1148 addn,subn : begin
1149 if not(cs_extsyntax in aktmoduleswitches) or
1150 (not(is_pchar(ld)) and not(m_add_pointer in aktmodeswitches)) then
1151 CGMessage(type_e_mismatch);
1152 { Dirty hack, to support multiple firstpasses (PFV) }
1153 if (p^.resulttype=nil) and
1154 (ld^.deftype=pointerdef) and
1155 (ppointerdef(ld)^.pointertype.def^.size>1) then
1156 begin
1157 p^.right:=gennode(muln,p^.right,
1158 genordinalconstnode(ppointerdef(ld)^.pointertype.def^.size,s32bitdef));
1159 firstpass(p^.right);
1160 end;
1161 end;
1162 else
1163 CGMessage(type_e_mismatch);
1164 end;
1165 convdone:=true;
1167 else
1169 if (rd^.deftype=procvardef) and (ld^.deftype=procvardef) and is_equal(rd,ld) then
1170 begin
1171 calcregisters(p,1,0,0);
1172 p^.location.loc:=LOC_REGISTER;
1173 case pt of
1174 equaln,unequaln : ;
1175 else
1176 CGMessage(type_e_mismatch);
1177 end;
1178 convdone:=true;
1180 else
1182 if (ld^.deftype=enumdef) and (rd^.deftype=enumdef) then
1183 begin
1184 if not(is_equal(ld,rd)) then
1185 begin
1186 p^.right:=gentypeconvnode(p^.right,ld);
1187 firstpass(p^.right);
1188 end;
1189 calcregisters(p,1,0,0);
1190 case pt of
1191 equaln,unequaln,
1192 ltn,lten,gtn,gten : ;
1193 else CGMessage(type_e_mismatch);
1194 end;
1195 convdone:=true;
1196 end;
1198 { the general solution is to convert to 32 bit int }
1199 if not convdone then
1200 begin
1201 { but an int/int gives real/real! }
1202 if pt=slashn then
1203 begin
1204 CGMessage(type_h_use_div_for_int);
1205 p^.right:=gentypeconvnode(p^.right,bestrealdef^);
1206 p^.left:=gentypeconvnode(p^.left,bestrealdef^);
1207 firstpass(p^.left);
1208 firstpass(p^.right);
1209 { maybe we need an integer register to save }
1210 { a reference }
1211 if ((p^.left^.location.loc<>LOC_FPU) or
1212 (p^.right^.location.loc<>LOC_FPU)) and
1213 (p^.left^.registers32=p^.right^.registers32) then
1214 calcregisters(p,1,1,0)
1215 else
1216 calcregisters(p,0,1,0);
1217 p^.location.loc:=LOC_FPU;
1219 else
1220 begin
1221 p^.right:=gentypeconvnode(p^.right,s32bitdef);
1222 p^.left:=gentypeconvnode(p^.left,s32bitdef);
1223 firstpass(p^.left);
1224 firstpass(p^.right);
1225 calcregisters(p,1,0,0);
1226 p^.location.loc:=LOC_REGISTER;
1227 end;
1228 end;
1230 if codegenerror then
1231 exit;
1233 { determines result type for comparions }
1234 { here the is a problem with multiple passes }
1235 { example length(s)+1 gets internal 'longint' type first }
1236 { if it is a arg it is converted to 'LONGINT' }
1237 { but a second first pass will reset this to 'longint' }
1238 case pt of
1239 ltn,lten,gtn,gten,equaln,unequaln:
1240 begin
1241 if (not assigned(p^.resulttype)) or
1242 (p^.resulttype^.deftype=stringdef) then
1243 p^.resulttype:=booldef;
1244 if is_64bitint(p^.left^.resulttype) then
1245 p^.location.loc:=LOC_JUMP
1246 else
1247 p^.location.loc:=LOC_FLAGS;
1248 end;
1249 xorn:
1250 begin
1251 if not assigned(p^.resulttype) then
1252 p^.resulttype:=p^.left^.resulttype;
1253 p^.location.loc:=LOC_REGISTER;
1254 end;
1255 addn:
1256 begin
1257 if not assigned(p^.resulttype) then
1258 begin
1259 { for strings, return is always a 255 char string }
1260 if is_shortstring(p^.left^.resulttype) then
1261 p^.resulttype:=cshortstringdef
1262 else
1263 p^.resulttype:=p^.left^.resulttype;
1264 end;
1265 end;
1266 else
1267 if not assigned(p^.resulttype) then
1268 p^.resulttype:=p^.left^.resulttype;
1269 end;
1270 end;
1273 end.
1275 $Log$
1276 Revision 1.1 2002/02/19 08:23:59 sasu
1277 Initial revision
1279 Revision 1.1.2.8 2000/12/16 15:54:51 jonas
1280 + warning when there is a chance to get a range check error because of
1281 automatic type conversion to u32bit
1283 Revision 1.1.2.7 2000/12/13 12:25:40 jonas
1284 + also added 64bit conversion when using cardinals and signed
1285 expressions for div (in tcmat this time :)
1286 * removed automatic type conversion back to dword of 64bit results
1288 Revision 1.1.2.6 2000/12/11 14:14:10 jonas
1289 * no longer use left type for conversion mentioned in previous commit,
1290 since it may not be 32bit. Always use u32bitdef instead.
1292 Revision 1.1.2.5 2000/12/11 11:47:41 jonas
1293 * automatically typecast result of 64bit evaluations of 32bit operations
1294 (when using range checking or when dividing) back to 32bits.
1296 Revision 1.1.2.4 2000/12/08 17:03:23 jonas
1297 + added full range checking for 64bit types
1298 * fixed web bug 1144
1300 Revision 1.1.2.3 2000/09/10 20:19:03 peter
1301 * fixed crash with smallset -> normalset conversion
1303 Revision 1.1.2.2 2000/07/27 09:17:38 jonas
1304 * removed obsolete typeconversion (it got removed by the compiler in
1305 firsttypeconv anyway)
1307 Revision 1.1.2.1 2000/07/19 05:55:33 michael
1308 + Applied patch from Pierre
1310 Revision 1.1 2000/07/13 06:29:58 michael
1311 + Initial import
1313 Revision 1.79 2000/06/02 21:24:48 pierre
1314 * operator overloading now uses isbinaryoperatoracceptable
1315 and is unaryoperatoracceptable
1317 Revision 1.78 2000/05/31 06:58:41 florian
1318 * forgot to commit a fix for the enumeration subrange problem, yesterday
1320 Revision 1.77 2000/05/11 17:53:40 peter
1321 * small fix for previous commit
1323 Revision 1.76 2000/05/11 16:47:37 peter
1324 * fixed check for overloaded operator with array and chararray check
1326 Revision 1.75 2000/04/25 14:43:36 jonas
1327 - disabled "string_var := string_var + ... " and "string_var + char_var"
1328 optimizations (were only active with -dnewoptimizations) because of
1329 several internal issues
1331 Revision 1.74 2000/04/21 12:35:05 jonas
1332 + special code for string + char, between -dnewoptimizations
1334 Revision 1.73 2000/03/28 21:14:18 pierre
1335 * fix for bug 891
1337 Revision 1.72 2000/03/20 10:16:51 florian
1338 * fixed <dword>/<dword>, <int64>/<int64> and <qword>/<qword>
1340 Revision 1.71 2000/03/18 15:01:19 jonas
1341 * moved a $maxfpuregisters directive a bit up because it was being
1342 ignored
1344 Revision 1.70 2000/02/19 10:12:48 florian
1345 * fixed one more internalerror 10
1347 Revision 1.69 2000/02/17 14:53:42 florian
1348 * some updates for the newcg
1350 Revision 1.68 2000/02/14 22:34:28 florian
1351 * fixed another internalerror
1353 Revision 1.67 2000/02/13 22:46:28 florian
1354 * fixed an internalerror with writeln
1355 * fixed arrayconstructor_to_set to force the generation of better code
1356 and added a more strict type checking
1358 Revision 1.66 2000/02/13 14:21:51 jonas
1359 * modifications to make the compiler functional when compiled with
1362 Revision 1.65 2000/02/09 13:23:06 peter
1363 * log truncated
1365 Revision 1.64 2000/02/04 08:47:10 florian
1366 * better register variable allocation in -Or mode
1368 Revision 1.63 2000/01/07 01:14:43 peter
1369 * updated copyright to 2000
1371 Revision 1.62 2000/01/04 20:10:20 florian
1372 * mmx support fixed
1374 Revision 1.61 1999/12/11 18:53:31 jonas
1375 * fixed type conversions of results of operations with cardinals
1376 (between -dcardinalmulfix)
1378 Revision 1.60 1999/12/09 23:18:04 pierre
1379 * no_fast_exit if procedure contains implicit termination code
1381 Revision 1.59 1999/12/01 12:42:33 peter
1382 * fixed bug 698
1383 * removed some notes about unused vars
1385 Revision 1.58 1999/11/30 10:40:56 peter
1386 + ttype, tsymlist
1388 Revision 1.57 1999/11/26 13:51:29 pierre
1389 * fix for overloading of shr shl mod and div
1391 Revision 1.56 1999/11/18 15:34:48 pierre
1392 * Notes/Hints for local syms changed to
1393 Set_varstate function
1395 Revision 1.55 1999/11/17 17:05:06 pierre
1396 * Notes/hints changes
1398 Revision 1.54 1999/11/16 23:45:28 pierre
1399 * global var token was changed by overload code (form bug 707)
1401 Revision 1.53 1999/11/15 21:53:42 peter
1402 * fixed constant eval for bool xor/or/and bool
1404 Revision 1.52 1999/11/15 17:53:00 pierre
1405 + one field added for ttoken record for operator
1406 linking the id to the corresponding operator token that
1407 can now now all be overloaded
1408 * overloaded operators are resetted to nil in InitSymtable
1409 (bug when trying to compile a uint that overloads operators twice)
1411 Revision 1.51 1999/11/06 14:34:29 peter
1412 * truncated log to 20 revs
1414 Revision 1.50 1999/09/27 23:45:00 peter
1415 * procinfo is now a pointer
1416 * support for result setting in sub procedure
1418 Revision 1.49 1999/09/16 13:39:14 peter
1419 * arrayconstructor 2 set conversion is now called always in the
1420 beginning of firstadd
1422 Revision 1.48 1999/09/15 20:35:45 florian
1423 * small fix to operator overloading when in MMX mode
1424 + the compiler uses now fldz and fld1 if possible
1425 + some fixes to floating point registers
1426 + some math. functions (arctan, ln, sin, cos, sqrt, sqr, pi) are now inlined
1427 * .... ???
1429 Revision 1.47 1999/09/13 16:28:05 peter
1430 * typo in previous commit open_array -> chararray :(
1432 Revision 1.46 1999/09/10 15:40:46 peter
1433 * fixed array check for operators, becuase array can also be a set
1435 Revision 1.45 1999/09/08 16:05:29 peter
1436 * pointer add/sub is now as expected and the same results as inc/dec