{ $Id$ Copyright (C) 1993-98 by Florian Klaempfl This unit provides some help routines for type handling This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. **************************************************************************** } unit types; interface uses objects,cobjects,globals,symtable,tree,aasm; type tmmxtype = (mmxno,mmxu8bit,mmxs8bit,mmxu16bit,mmxs16bit, mmxu32bit,mmxs32bit,mmxfixed16,mmxsingle); { returns true, if def defines an ordinal type } function is_ordinal(def : pdef) : boolean; { true if p points to an open array def } function is_open_array(p : pdef) : boolean; { returns true, if def defines a signed data type (only for ordinal types) } function is_signed(def : pdef) : boolean; { returns true, if def uses FPU } function is_fpu(def : pdef) : boolean; { true if the return value is in EAX } function ret_in_acc(def : pdef) : boolean; { true if uses a parameter as return value } function ret_in_param(def : pdef) : boolean; { true if a const parameter is too large to copy } function dont_copy_const_param(def : pdef) : boolean; { true if we must never copy this parameter } const never_copy_const_param : boolean = false; { true, if def1 and def2 are semantical the same } function is_equal(def1,def2 : pdef) : boolean; { checks for type compatibility (subgroups of type) } { used for case statements... probably missing stuff } { to use on other types } function is_subequal(def1, def2: pdef): boolean; { true, if two parameter lists are equal } function equal_paras(def1,def2 : pdefcoll) : boolean; { gibt den ordinalen Werten der Node zurueck oder falls sie } { keinen ordinalen Wert hat, wird ein Fehler erzeugt } function get_ordinal_value(p : ptree) : longint; { if l isn't in the range of def a range check error is generated } procedure testrange(def : pdef;l : longint); { returns the range of def } procedure getrange(def : pdef;var l : longint;var h : longint); { generates a VMT for _class } procedure genvmt(_class : pobjectdef); { true, if p is a pointer to a const int value } function is_constintnode(p : ptree) : boolean; { like is_constintnode } function is_constboolnode(p : ptree) : boolean; function is_constrealnode(p : ptree) : boolean; function is_constcharnode(p : ptree) : boolean; { some type helper routines for MMX support } function is_mmx_able_array(p : pdef) : boolean; { returns the mmx type } function mmx_type(p : pdef) : tmmxtype; implementation uses verbose; function is_constintnode(p : ptree) : boolean; begin {DM: According to me, an orddef with anysize, is a correct constintnode. Anyway I commented changed s32bit check, because it caused problems with statements like a:=high(word).} is_constintnode:=((p^.treetype=ordconstn) and (p^.resulttype^.deftype=orddef) and (porddef(p^.resulttype)^.typ in [u8bit,s8bit,u16bit,s16bit, u32bit,s32bit,uauto])); end; function is_constcharnode(p : ptree) : boolean; begin is_constcharnode:=((p^.treetype=ordconstn) and (p^.resulttype^.deftype=orddef) and (porddef(p^.resulttype)^.typ=uchar)); end; function is_constrealnode(p : ptree) : boolean; begin is_constrealnode:=(p^.treetype=realconstn); end; function is_constboolnode(p : ptree) : boolean; begin is_constboolnode:=((p^.treetype=ordconstn) and (p^.resulttype^.deftype=orddef) and (porddef(p^.resulttype)^.typ=bool8bit)); end; function equal_paras(def1,def2 : pdefcoll) : boolean; begin while (assigned(def1)) and (assigned(def2)) do begin if not(is_equal(def1^.data,def2^.data)) or (def1^.paratyp<>def2^.paratyp) then begin equal_paras:=false; exit; end; def1:=def1^.next; def2:=def2^.next; end; if (def1=nil) and (def2=nil) then equal_paras:=true else equal_paras:=false; end; { returns true, if def uses FPU } function is_fpu(def : pdef) : boolean; begin is_fpu:=(def^.deftype=floatdef) and (pfloatdef(def)^.typ<>f32bit); end; function is_ordinal(def : pdef) : boolean; var dt : tbasetype; begin case def^.deftype of orddef : begin dt:=porddef(def)^.typ; is_ordinal:=(dt=s32bit) or (dt=u32bit) or (dt=uchar) or (dt=u8bit) or (dt=s8bit) or (dt=s16bit) or (dt=bool8bit) or (dt=u16bit); end; enumdef : is_ordinal:=true; else is_ordinal:=false; end; end; function is_signed(def : pdef) : boolean; var dt : tbasetype; begin case def^.deftype of orddef : begin dt:=porddef(def)^.typ; is_signed:=(dt=s32bit) or (dt=s8bit) or (dt=s16bit); end; enumdef : is_signed:=false; else internalerror(1001); end; end; { true, if p points to an open array def } function is_open_array(p : pdef) : boolean; begin is_open_array:=(p^.deftype=arraydef) and (parraydef(p)^.lowrange=0) and (parraydef(p)^.highrange=-1); end; { true if the return value is in accumulator (EAX for i386), D0 for 68k } function ret_in_acc(def : pdef) : boolean; begin ret_in_acc:=(def^.deftype=orddef) or (def^.deftype=pointerdef) or (def^.deftype=enumdef) or (def^.deftype=procvardef) or (def^.deftype=classrefdef) or ((def^.deftype=objectdef) and ((pobjectdef(def)^.options and oois_class)<>0) ) or ((def^.deftype=setdef) and (psetdef(def)^.settype=smallset)) or ((def^.deftype=floatdef) and (pfloatdef(def)^.typ=f32bit)); end; { true if uses a parameter as return value } function ret_in_param(def : pdef) : boolean; begin ret_in_param:=(def^.deftype=arraydef) or (def^.deftype=stringdef) or ((def^.deftype=objectdef) and ((pobjectdef(def)^.options and oois_class)=0) ) or (def^.deftype=recorddef) or ((def^.deftype=setdef) and (psetdef(def)^.settype<>smallset)); end; { true if a const parameter is too large to copy } function dont_copy_const_param(def : pdef) : boolean; begin dont_copy_const_param:=(def^.deftype=arraydef) or (def^.deftype=stringdef) or (def^.deftype=objectdef) or (def^.deftype=formaldef) or (def^.deftype=recorddef) or (def^.deftype=formaldef) or ((def^.deftype=setdef) and (psetdef(def)^.settype<>smallset)); end; procedure testrange(def : pdef;l : longint); var lv,hv: longint; begin getrange(def,lv,hv); if (def^.deftype=orddef) and (porddef(def)^.typ=u32bit) then begin if lv<=hv then begin if (lhv) then Message(parser_e_range_check_error); end else { this happens with the wrap around problem } { if lv is positive and hv is over $7ffffff } { so it seems negative } begin if ((l>=0) and (lhv)) then Message(parser_e_range_check_error); end; end else if (lhv) then Message(parser_e_range_check_error); end; procedure getrange(def : pdef;var l : longint;var h : longint); begin if def^.deftype=orddef then case porddef(def)^.typ of s32bit,s16bit,u16bit,s8bit,u8bit : begin l:=porddef(def)^.von; h:=porddef(def)^.bis; end; bool8bit : begin l:=0; h:=1; end; uchar : begin l:=0; h:=255; end; u32bit : begin { this should work now } l:=porddef(def)^.von; h:=porddef(def)^.bis; end; end else if def^.deftype=enumdef then begin l:=0; h:=penumdef(def)^.max; end; end; function get_ordinal_value(p : ptree) : longint; begin if p^.treetype=ordconstn then get_ordinal_value:=p^.value else Message(parser_e_ordinal_expected); end; function mmx_type(p : pdef) : tmmxtype; begin mmx_type:=mmxno; if is_mmx_able_array(p) then begin if parraydef(p)^.definition^.deftype=floatdef then case pfloatdef(parraydef(p)^.definition)^.typ of s32real: mmx_type:=mmxsingle; f16bit: mmx_type:=mmxfixed16 end else case porddef(parraydef(p)^.definition)^.typ of u8bit: mmx_type:=mmxu8bit; s8bit: mmx_type:=mmxs8bit; u16bit: mmx_type:=mmxu16bit; s16bit: mmx_type:=mmxs16bit; u32bit: mmx_type:=mmxu32bit; s32bit: mmx_type:=mmxs32bit; end; end; end; function is_mmx_able_array(p : pdef) : boolean; begin {$ifdef SUPPORT_MMX} if (cs_mmx_saturation in aktswitches) then begin is_mmx_able_array:=(p^.deftype=arraydef) and ( ((parraydef(p)^.definition^.deftype=orddef) and ( (parraydef(p)^.lowrange=0) and (parraydef(p)^.highrange=1) and (porddef(parraydef(p)^.definition)^.typ in [u32bit,s32bit]) ) or ( (parraydef(p)^.lowrange=0) and (parraydef(p)^.highrange=3) and (porddef(parraydef(p)^.definition)^.typ in [u16bit,s16bit]) ) ) ) or ( ((parraydef(p)^.definition^.deftype=floatdef) and ( (parraydef(p)^.lowrange=0) and (parraydef(p)^.highrange=3) and (pfloatdef(parraydef(p)^.definition)^.typ=f16bit) ) or ( (parraydef(p)^.lowrange=0) and (parraydef(p)^.highrange=1) and (pfloatdef(parraydef(p)^.definition)^.typ=s32real) ) ) ); end else begin is_mmx_able_array:=(p^.deftype=arraydef) and ( ((parraydef(p)^.definition^.deftype=orddef) and ( (parraydef(p)^.lowrange=0) and (parraydef(p)^.highrange=1) and (porddef(parraydef(p)^.definition)^.typ in [u32bit,s32bit]) ) or ( (parraydef(p)^.lowrange=0) and (parraydef(p)^.highrange=3) and (porddef(parraydef(p)^.definition)^.typ in [u16bit,s16bit]) ) or ( (parraydef(p)^.lowrange=0) and (parraydef(p)^.highrange=7) and (porddef(parraydef(p)^.definition)^.typ in [u8bit,s8bit]) ) ) ) or ( ((parraydef(p)^.definition^.deftype=floatdef) and ( (parraydef(p)^.lowrange=0) and (parraydef(p)^.highrange=3) and (pfloatdef(parraydef(p)^.definition)^.typ=f32bit) ) or ( (parraydef(p)^.lowrange=0) and (parraydef(p)^.highrange=1) and (pfloatdef(parraydef(p)^.definition)^.typ=s32real) ) ) ); end; {$else SUPPORT_MMX} is_mmx_able_array:=false; {$endif SUPPORT_MMX} end; function is_equal(def1,def2 : pdef) : boolean; var b : boolean; hd : pdef; hp1,hp2 : pdefcoll; begin { both types must exists } if not (assigned(def1) and assigned(def2)) then begin is_equal:=false; exit; end; { be sure, that if there is a stringdef, that this is def1 } if def2^.deftype=stringdef then begin hd:=def1; def1:=def2; def2:=hd; end; b:=false; { wenn beide auf die gleiche Definition zeigen sind sie wohl gleich...} if def1=def2 then b:=true else { pointer with an equal definition are equal } if (def1^.deftype=pointerdef) and (def2^.deftype=pointerdef) then { here a problem detected in tabsolutesym } { the types can be forward type !! } begin if assigned(def1^.sym) and ((def1^.sym^.properties and sp_forwarddef)<>0) then b:=(def1^.sym=def2^.sym) else b:=is_equal(ppointerdef(def1)^.definition,ppointerdef(def2)^.definition); end else { Grundtypen sind gleich, wenn sie den selben Grundtyp haben, } { und wenn noetig den selben Unterbereich haben } if (def1^.deftype=orddef) and (def2^.deftype=orddef) then begin case porddef(def1)^.typ of u32bit,u8bit,s32bit,s8bit,u16bit,s16bit : begin if porddef(def1)^.typ=porddef(def2)^.typ then if (porddef(def1)^.von=porddef(def2)^.von) and (porddef(def1)^.bis=porddef(def2)^.bis) then b:=true; end; uvoid,bool8bit,uchar : b:=porddef(def1)^.typ=porddef(def2)^.typ; end; end else if (def1^.deftype=floatdef) and (def2^.deftype=floatdef) then b:=pfloatdef(def1)^.typ=pfloatdef(def2)^.typ else { strings with the same length are equal } if (def1^.deftype=stringdef) and (def2^.deftype=stringdef) and (pstringdef(def1)^.len=pstringdef(def2)^.len) then b:=true { STRING[N] ist equivalent zu ARRAY[0..N] OF CHAR (N<256) } { else if ((def1^.deftype=stringdef) and (def2^.deftype=arraydef)) and (parraydef(def2)^.definition^.deftype=orddef) and (porddef(parraydef(def1)^.definition)^.typ=uchar) and (parraydef(def2)^.lowrange=0) and (parraydef(def2)^.highrange=pstringdef(def1)^.len) then b:=true } else if (def1^.deftype=formaldef) and (def2^.deftype=formaldef) then b:=true { file types with the same file element type are equal } { this is a problem for assign !! } { changed to allow if one is untyped } { all typed files are equal to the special } { typed file that has voiddef as elemnt type } { but must NOT match for text file !!! } else if (def1^.deftype=filedef) and (def2^.deftype=filedef) then b:=(pfiledef(def1)^.filetype=pfiledef(def2)^.filetype) and (( ((pfiledef(def1)^.typed_as=nil) and (pfiledef(def2)^.typed_as=nil)) or ( (pfiledef(def1)^.typed_as<>nil) and (pfiledef(def2)^.typed_as<>nil) and is_equal(pfiledef(def1)^.typed_as,pfiledef(def2)^.typed_as) ) or ( (pfiledef(def1)^.typed_as=pdef(voiddef)) or (pfiledef(def2)^.typed_as=pdef(voiddef)) ))) { sets with the same element type are equal } else if (def1^.deftype=setdef) and (def2^.deftype=setdef) then begin if assigned(psetdef(def1)^.setof) and assigned(psetdef(def2)^.setof) then b:=is_equal(psetdef(def1)^.setof,psetdef(def2)^.setof) else b:=true; end else if (def1^.deftype=procvardef) and (def2^.deftype=procvardef) then begin { poassembler isn't important for compatibility } b:=((pprocvardef(def1)^.options and not(poassembler))= (pprocvardef(def2)^.options and not(poassembler)) ) and is_equal(pprocvardef(def1)^.retdef,pprocvardef(def2)^.retdef); { now evalute the parameters } if b then begin hp1:=pprocvardef(def1)^.para1; hp2:=pprocvardef(def1)^.para1; while assigned(hp1) and assigned(hp2) do begin if not(is_equal(hp1^.data,hp2^.data)) or not(hp1^.paratyp=hp2^.paratyp) then begin b:=false; break; end; hp1:=hp1^.next; hp2:=hp2^.next; end; b:=(hp1=nil) and (hp2=nil); end; end else if (def1^.deftype=arraydef) and (def2^.deftype=arraydef) and (is_open_array(def1) or is_open_array(def2)) then begin b:=is_equal(parraydef(def1)^.definition,parraydef(def2)^.definition); end else if (def1^.deftype=classrefdef) and (def2^.deftype=classrefdef) then begin { similar to pointerdef: } if assigned(def1^.sym) and ((def1^.sym^.properties and sp_forwarddef)<>0) then b:=(def1^.sym=def2^.sym) else b:=is_equal(pclassrefdef(def1)^.definition,pclassrefdef(def2)^.definition); end; is_equal:=b; end; function is_subequal(def1, def2: pdef): boolean; Begin if assigned(def1) and assigned(def2) then Begin is_subequal := FALSE; if (def1^.deftype = orddef) and (def2^.deftype = orddef) then Begin { see p.47 of Turbo Pascal 7.01 manual for the separation of types } { range checking for case statements is done with testrange } case porddef(def1)^.typ of s32bit,u32bit,u8bit,s8bit,s16bit,u16bit: Begin { PROBABLE CODE GENERATION BUG HERE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! } { if porddef(def2)^.typ in [s32bit,u32bit,u8bit,s8bit,s16bit,u16bit] then is_subequal := TRUE; } if (porddef(def2)^.typ = s32bit) or (porddef(def2)^.typ = u32bit) or (porddef(def2)^.typ = u8bit) or (porddef(def2)^.typ = s8bit) or (porddef(def2)^.typ = s16bit) or (porddef(def2)^.typ = u16bit) then Begin is_subequal:=TRUE; end; end; bool8bit: if porddef(def2)^.typ = bool8bit then is_subequal := TRUE; uchar: if porddef(def2)^.typ = uchar then is_subequal := TRUE; end; end else Begin { I assume that both enumerations are equal when the first } { pointers are equal. } if (def1^.deftype = enumdef) and (def2^.deftype =enumdef) then Begin if penumdef(def1)^.first = penumdef(def2)^.first then is_subequal := TRUE; end; end; end; { endif assigned ... } end; type pprocdefcoll = ^tprocdefcoll; tprocdefcoll = record next : pprocdefcoll; data : pprocdef; end; psymcoll = ^tsymcoll; tsymcoll = record next : psymcoll; name : pstring; data : pprocdefcoll; end; var wurzel : psymcoll; nextvirtnumber : longint; _c : pobjectdef; has_constructor,has_virtual_method : boolean; procedure eachsym(sym : psym);{$ifndef FPC}far;{$endif} var procdefcoll : pprocdefcoll; hp : pprocdef; symcoll : psymcoll; _name : string; stored : boolean; begin { nur Unterprogrammsymbole werden in die VMT aufgenommen } if sym^.typ=procsym then begin _name:=sym^.name; symcoll:=wurzel; while assigned(symcoll) do begin { wenn das Symbol in der Liste schon existiert } if _name=symcoll^.name^ then begin { walk thorugh all defs of the symbol } hp:=pprocsym(sym)^.definition; while assigned(hp) do begin { compare with all stored definitions } procdefcoll:=symcoll^.data; stored:=false; while assigned(procdefcoll) do begin { compare parameters } if equal_paras(procdefcoll^.data^.para1,hp^.para1) and ( ((procdefcoll^.data^.options and povirtualmethod)<>0) or ((hp^.options and povirtualmethod)<>0) ) then begin { wenn sie gleich sind } { und eine davon virtual deklariert ist } { Fehler falls nur eine VIRTUAL } if (procdefcoll^.data^.options and povirtualmethod)<> (hp^.options and povirtualmethod) then Message1(parser_e_overloaded_are_not_both_virtual,_c^.name^+'.'+_name); { check, if the overridden directive is set } { (povirtualmethod is set! } { class ? } if ((_c^.options and oois_class)<>0) and ((hp^.options and pooverridingmethod)=0) then Message1(parser_e_must_use_override,_c^.name^+'.'+_name); { error, if the return types aren't equal } if not(is_equal(procdefcoll^.data^.retdef,hp^.retdef)) then Message1(parser_e_overloaded_methodes_not_same_ret,_c^.name^+'.'+_name); { the flags have to match } { except abstract and override } if (procdefcoll^.data^.options and not(poabstractmethod or pooverridingmethod))<> (hp^.options and not(poabstractmethod or pooverridingmethod)) then Message1(parser_e_header_dont_match_forward,_c^.name^+'.'+_name); { now set the number } hp^.extnumber:=procdefcoll^.data^.extnumber; { and exchange } procdefcoll^.data:=hp; stored:=true; end; procdefcoll:=procdefcoll^.next; end; { if it isn't saved in the list } { we create a new entry } if not(stored) then begin new(procdefcoll); procdefcoll^.data:=hp; procdefcoll^.next:=symcoll^.data; symcoll^.data:=procdefcoll; { if the method is virtual ... } if (hp^.options and povirtualmethod)<>0 then begin { ... it will get a number } hp^.extnumber:=nextvirtnumber; inc(nextvirtnumber); end; { check, if a method should be overridden } if (hp^.options and pooverridingmethod)<>0 then Message1(parser_e_nothing_to_be_overridden,_c^.name^+'.'+_name); end; hp:=hp^.nextoverloaded; end; exit; end; symcoll:=symcoll^.next; end; { if not, generate a new symbol item } new(symcoll); symcoll^.name:=stringdup(sym^.name); symcoll^.next:=wurzel; symcoll^.data:=nil; wurzel:=symcoll; hp:=pprocsym(sym)^.definition; { inserts all definitions } while assigned(hp) do begin new(procdefcoll); procdefcoll^.data:=hp; procdefcoll^.next:=symcoll^.data; symcoll^.data:=procdefcoll; { if it's a virtual method } if (hp^.options and povirtualmethod)<>0 then begin { then it gets a number ... } hp^.extnumber:=nextvirtnumber; { and we inc the number } inc(nextvirtnumber); has_virtual_method:=true; end; if (hp^.options and poconstructor)<>0 then has_constructor:=true; { check, if a method should be overridden } if (hp^.options and pooverridingmethod)<>0 then Message1(parser_e_nothing_to_be_overridden,_c^.name^+'.'+_name); { next overloaded method } hp:=hp^.nextoverloaded; end; end; end; procedure genvmt(_class : pobjectdef); procedure do_genvmt(p : pobjectdef); begin { start with the base class } if assigned(p^.childof) then do_genvmt(p^.childof); { walk through all public syms } _c:=_class; {$ifdef tp} p^.publicsyms^.foreach(eachsym); {$else} p^.publicsyms^.foreach(@eachsym); {$endif} end; var symcoll : psymcoll; procdefcoll : pprocdefcoll; i : longint; begin wurzel:=nil; nextvirtnumber:=0; has_constructor:=false; has_virtual_method:=false; { generates a tree of all used methods } do_genvmt(_class); if has_virtual_method and not(has_constructor) then begin exterror:=strpnew(_class^.name^); Message(parser_w_virtual_without_constructor); end; { generates the VMT } { walk trough all numbers for virtual methods and search } { the method } for i:=0 to nextvirtnumber-1 do begin symcoll:=wurzel; { walk trough all symbols } while assigned(symcoll) do begin { walk trough all methods } procdefcoll:=symcoll^.data; while assigned(procdefcoll) do begin { writes the addresses to the VMT } { but only this which are declared as virtual } if procdefcoll^.data^.extnumber=i then begin if (procdefcoll^.data^.options and povirtualmethod)<>0 then begin { if a method is abstract, then is also the } { class abstract and it's not allow to } { generates an instance } if (procdefcoll^.data^.options and poabstractmethod)<>0 then begin _class^.options:=_class^.options or oois_abstract; datasegment^.concat(new(pai_const,init_symbol('ABSTRACTERROR'))); end else begin datasegment^.concat(new(pai_const,init_symbol( strpnew(procdefcoll^.data^.mangledname)))); if (procdefcoll^.data^.options and povirtualmethod)<>0 then maybe_concat_external(procdefcoll^.data^.owner, procdefcoll^.data^.mangledname); end; end; end; procdefcoll:=procdefcoll^.next; end; symcoll:=symcoll^.next; end; end; { disposes the above generated tree } symcoll:=wurzel; while assigned(symcoll) do begin wurzel:=symcoll^.next; stringdispose(symcoll^.name); procdefcoll:=symcoll^.data; while assigned(procdefcoll) do begin symcoll^.data:=procdefcoll^.next; dispose(procdefcoll); procdefcoll:=symcoll^.data; end; dispose(symcoll); symcoll:=wurzel; end; end; end. { $Log$ Revision 1.3 1998-04-08 11:34:22 peter * nasm works (linux only tested) Revision 1.2 1998/03/28 23:09:57 florian * secondin bugfix (m68k and i386) * overflow checking bugfix (m68k and i386) -- pretty useless in secondadd, since everything is done using 32-bit * loading pointer to routines hopefully fixed (m68k) * flags problem with calls to RTL internal routines fixed (still strcmp to fix) (m68k) * #ELSE was still incorrect (didn't take care of the previous level) * problem with filenames in the command line solved * problem with mangledname solved * linking name problem solved (was case insensitive) * double id problem and potential crash solved * stop after first error * and=>test problem removed * correct read for all float types * 2 sigsegv fixes and a cosmetic fix for Internal Error * push/pop is now correct optimized (=> mov (%esp),reg) Revision 1.1.1.1 1998/03/25 11:18:15 root * Restored version Revision 1.24 1998/03/21 23:59:40 florian * indexed properties fixed * ppu i/o of properties fixed * field can be also used for write access * overriding of properties Revision 1.23 1998/03/20 23:31:35 florian * bug0113 fixed * problem with interdepened units fixed ("options.pas problem") * two small extensions for future AMD 3D support Revision 1.22 1998/03/10 01:17:30 peter * all files have the same header * messages are fully implemented, EXTDEBUG uses Comment() + AG... files for the Assembler generation Revision 1.21 1998/03/06 01:09:01 peter * removed the conflicts that had occured Revision 1.20 1998/03/06 00:53:01 peter * replaced all old messages from errore.msg, only ExtDebug and some Comment() calls are left * fixed options.pas Revision 1.19 1998/03/05 22:40:56 florian + warning about missing constructor added Revision 1.18 1998/03/04 17:34:14 michael + Changed ifdef FPK to ifdef FPC Revision 1.17 1998/03/02 01:49:38 peter * renamed target_DOS to target_GO32V1 + new verbose system, merged old errors and verbose units into one new verbose.pas, so errors.pas is obsolete Revision 1.16 1998/02/13 10:35:55 daniel * Made Motorola version compilable. * Fixed optimizer Revision 1.15 1998/02/12 17:19:33 florian * fixed to get remake3 work, but needs additional fixes (output, I don't like also that aktswitches isn't a pointer) Revision 1.14 1998/02/12 11:50:52 daniel Yes! Finally! After three retries, my patch! Changes: Complete rewrite of psub.pas. Added support for DLL's. Compiler requires less memory. Platform units for each platform. Revision 1.13 1998/02/11 21:56:41 florian * bugfixes: bug0093, bug0053, bug0088, bug0087, bug0089 Revision 1.12 1998/02/07 23:05:08 florian * once more MMX Revision 1.11 1998/02/06 10:34:35 florian * bug0082 and bug0084 fixed Revision 1.10 1998/02/05 22:27:07 florian * small problems fixed: remake3 should now work Revision 1.9 1998/02/05 21:54:36 florian + more MMX Revision 1.8 1998/01/31 00:43:37 carl - removed in in is_subequal, because the code generator is buggy! (instead uses if...) Revision 1.7 1998/01/16 18:03:21 florian * small bug fixes, some stuff of delphi styled constructores added Revision 1.6 1998/01/11 19:24:35 carl + type checking routine (is_subequal) for case statements Revision 1.5 1998/01/09 23:08:38 florian + C++/Delphi styled //-comments * some bugs in Delphi object model fixed + override directive Revision 1.4 1998/01/09 16:08:24 florian * abstract methods call now abstracterrorproc if they are called a class with an abstract method can be create with a class reference else the compiler forbides this Revision 1.3 1998/01/07 00:17:12 michael Restored released version (plus fixes) as current Revision 1.2 1997/11/28 18:14:51 pierre working version with several bug fixes Revision 1.1.1.1 1997/11/27 08:33:03 michael FPC Compiler CVS start Pre-CVS log: CEC Carl-Eric Codere FK Florian Klaempfl PM Pierre Muller + feature added - removed * bug fixed or changed History: 22th september 1997 + function dont_copy_const_param added (FK) 25th september 1997 + is_open_array added (FK) + is_equal handles now also open arrays (FK) 2nd october 1997 + added then boolean never_copy_const_param for use in typed write where we must push the reference anyway (PM) 3rd october 1997: + renamed ret_in_eax to ret_in_acc (for accumulator for port.) (CEC) - removed reference to i386 unit (CEC) 25th october 1997: * poassembler isn't important for compatiblity of proc vars (FK) 3rd november 1997: + added formaldef type to types where we dont_copy_const_param (PM) 20rd november 1997: + added is_fpu function (PM) }