mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-05-01 16:33:41 +02:00
912 lines
37 KiB
ObjectPascal
912 lines
37 KiB
ObjectPascal
{
|
|
$Id$
|
|
Copyright (c) 1998-2000 by Florian Klaempfl
|
|
|
|
Reads typed constants
|
|
|
|
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 ptconst;
|
|
|
|
{$i defines.inc}
|
|
|
|
interface
|
|
|
|
uses symtype,symsym;
|
|
|
|
{ this procedure reads typed constants }
|
|
{ sym is only needed for ansi strings }
|
|
{ the assembler label is in the middle (PM) }
|
|
procedure readtypedconst(def : pdef;sym : ptypedconstsym;no_change_allowed : boolean);
|
|
|
|
implementation
|
|
|
|
uses
|
|
{$ifdef Delphi}
|
|
sysutils,
|
|
{$else}
|
|
strings,
|
|
{$endif Delphi}
|
|
globtype,systems,tokens,cpuinfo,
|
|
cutils,globals,scanner,
|
|
symconst,symbase,symdef,symtable,aasm,types,verbose,
|
|
{ pass 1 }
|
|
node,pass_1,
|
|
nmat,nadd,ncal,nmem,nset,ncnv,ninl,ncon,nld,nflw,
|
|
{ parser specific stuff }
|
|
pbase,pexpr,
|
|
{ codegen }
|
|
hcodegen
|
|
{$ifdef newcg}
|
|
,cgbase
|
|
{$endif}
|
|
;
|
|
|
|
{$ifdef fpc}
|
|
{$maxfpuregisters 0}
|
|
{$endif fpc}
|
|
{ this procedure reads typed constants }
|
|
procedure readtypedconst(def : pdef;sym : ptypedconstsym;no_change_allowed : boolean);
|
|
|
|
var
|
|
{$ifdef m68k}
|
|
j : longint;
|
|
{$endif m68k}
|
|
len,base : longint;
|
|
p,hp : tnode;
|
|
i,l,offset,
|
|
strlength : longint;
|
|
curconstsegment : TAAsmoutput;
|
|
ll : pasmlabel;
|
|
s : string;
|
|
ca : pchar;
|
|
tmpguid : tguid;
|
|
aktpos : longint;
|
|
obj : pobjectdef;
|
|
symt : psymtable;
|
|
value : bestreal;
|
|
strval : pchar;
|
|
|
|
procedure check_range;
|
|
begin
|
|
if ((tordconstnode(p).value>porddef(def)^.high) or
|
|
(tordconstnode(p).value<porddef(def)^.low)) then
|
|
begin
|
|
if (cs_check_range in aktlocalswitches) then
|
|
Message(parser_e_range_check_error)
|
|
else
|
|
Message(parser_w_range_check_error);
|
|
end;
|
|
end;
|
|
|
|
{$R-} {Range check creates problem with init_8bit(-1) !!}
|
|
begin
|
|
if no_change_allowed then
|
|
curconstsegment:=consts
|
|
else
|
|
curconstsegment:=datasegment;
|
|
case def^.deftype of
|
|
orddef:
|
|
begin
|
|
p:=comp_expr(true);
|
|
do_firstpass(p);
|
|
case porddef(def)^.typ of
|
|
bool8bit :
|
|
begin
|
|
if is_constboolnode(p) then
|
|
curconstSegment.concat(Tai_const.Create_8bit(tordconstnode(p).value))
|
|
else
|
|
Message(cg_e_illegal_expression);
|
|
end;
|
|
bool16bit :
|
|
begin
|
|
if is_constboolnode(p) then
|
|
curconstSegment.concat(Tai_const.Create_16bit(tordconstnode(p).value))
|
|
else
|
|
Message(cg_e_illegal_expression);
|
|
end;
|
|
bool32bit :
|
|
begin
|
|
if is_constboolnode(p) then
|
|
curconstSegment.concat(Tai_const.Create_32bit(tordconstnode(p).value))
|
|
else
|
|
Message(cg_e_illegal_expression);
|
|
end;
|
|
uchar :
|
|
begin
|
|
if is_constcharnode(p) then
|
|
curconstSegment.concat(Tai_const.Create_8bit(tordconstnode(p).value))
|
|
else
|
|
Message(cg_e_illegal_expression);
|
|
end;
|
|
uwidechar :
|
|
begin
|
|
if is_constcharnode(p) then
|
|
curconstSegment.concat(Tai_const.Create_16bit(tordconstnode(p).value))
|
|
else
|
|
Message(cg_e_illegal_expression);
|
|
end;
|
|
s8bit,
|
|
u8bit :
|
|
begin
|
|
if is_constintnode(p) then
|
|
begin
|
|
curconstSegment.concat(Tai_const.Create_8bit(tordconstnode(p).value));
|
|
check_range;
|
|
end
|
|
else
|
|
Message(cg_e_illegal_expression);
|
|
end;
|
|
u16bit,
|
|
s16bit :
|
|
begin
|
|
if is_constintnode(p) then
|
|
begin
|
|
curconstSegment.concat(Tai_const.Create_16bit(tordconstnode(p).value));
|
|
check_range;
|
|
end
|
|
else
|
|
Message(cg_e_illegal_expression);
|
|
end;
|
|
s32bit,
|
|
u32bit :
|
|
begin
|
|
if is_constintnode(p) then
|
|
begin
|
|
curconstSegment.concat(Tai_const.Create_32bit(tordconstnode(p).value));
|
|
if porddef(def)^.typ<>u32bit then
|
|
check_range;
|
|
end
|
|
else
|
|
Message(cg_e_illegal_expression);
|
|
end;
|
|
s64bit,
|
|
u64bit:
|
|
begin
|
|
if is_constintnode(p) then
|
|
begin
|
|
{!!!!! hmmm, we can write yet only consts til 2^32-1 :( (FK) }
|
|
curconstSegment.concat(Tai_const.Create_32bit(tordconstnode(p).value));
|
|
curconstSegment.concat(Tai_const.Create_32bit(0));
|
|
end
|
|
else
|
|
Message(cg_e_illegal_expression);
|
|
end;
|
|
else
|
|
internalerror(3799);
|
|
end;
|
|
p.free;
|
|
end;
|
|
floatdef:
|
|
begin
|
|
p:=comp_expr(true);
|
|
do_firstpass(p);
|
|
if is_constrealnode(p) then
|
|
value:=trealconstnode(p).value_real
|
|
else if is_constintnode(p) then
|
|
value:=tordconstnode(p).value
|
|
else
|
|
Message(cg_e_illegal_expression);
|
|
|
|
case pfloatdef(def)^.typ of
|
|
s32real :
|
|
curconstSegment.concat(Tai_real_32bit.Create(value));
|
|
s64real :
|
|
curconstSegment.concat(Tai_real_64bit.Create(value));
|
|
s80real :
|
|
curconstSegment.concat(Tai_real_80bit.Create(value));
|
|
s64comp :
|
|
curconstSegment.concat(Tai_comp_64bit.Create(value));
|
|
f32bit :
|
|
curconstSegment.concat(Tai_const.Create_32bit(trunc(value*65536)));
|
|
else
|
|
internalerror(18);
|
|
end;
|
|
p.free;
|
|
end;
|
|
classrefdef:
|
|
begin
|
|
p:=comp_expr(true);
|
|
do_firstpass(p);
|
|
case p.nodetype of
|
|
loadvmtn:
|
|
begin
|
|
if not(pobjectdef(pclassrefdef(p.resulttype)^.pointertype.def)^.is_related(
|
|
pobjectdef(pclassrefdef(def)^.pointertype.def))) then
|
|
Message(cg_e_illegal_expression);
|
|
curconstSegment.concat(Tai_const_symbol.Create(newasmsymbol(pobjectdef(
|
|
pclassrefdef(p.resulttype)^.pointertype.def)^.vmt_mangledname)));
|
|
end;
|
|
niln:
|
|
curconstSegment.concat(Tai_const.Create_32bit(0));
|
|
else Message(cg_e_illegal_expression);
|
|
end;
|
|
p.free;
|
|
end;
|
|
pointerdef:
|
|
begin
|
|
p:=comp_expr(true);
|
|
do_firstpass(p);
|
|
if (p.nodetype=typeconvn) and
|
|
(ttypeconvnode(p).left.nodetype in [addrn,niln]) and
|
|
is_equal(def,p.resulttype) then
|
|
begin
|
|
hp:=ttypeconvnode(p).left;
|
|
ttypeconvnode(p).left:=nil;
|
|
p.free;
|
|
p:=hp;
|
|
end;
|
|
{ allows horrible ofs(typeof(TButton)^) code !! }
|
|
if (p.nodetype=addrn) and
|
|
(taddrnode(p).left.nodetype=derefn) then
|
|
begin
|
|
hp:=tderefnode(taddrnode(p).left).left;
|
|
tderefnode(taddrnode(p).left).left:=nil;
|
|
p.free;
|
|
p:=hp;
|
|
end;
|
|
{ nil pointer ? }
|
|
if p.nodetype=niln then
|
|
curconstSegment.concat(Tai_const.Create_32bit(0))
|
|
{ maybe pchar ? }
|
|
else
|
|
if is_char(ppointerdef(def)^.pointertype.def) and
|
|
(p.nodetype<>addrn) then
|
|
begin
|
|
getdatalabel(ll);
|
|
curconstSegment.concat(Tai_const_symbol.Create(ll));
|
|
Consts.concat(Tai_label.Create(ll));
|
|
if p.nodetype=stringconstn then
|
|
begin
|
|
len:=tstringconstnode(p).len;
|
|
{ For tp7 the maximum lentgh can be 255 }
|
|
if (m_tp in aktmodeswitches) and
|
|
(len>255) then
|
|
len:=255;
|
|
getmem(ca,len+2);
|
|
move(tstringconstnode(p).value_str^,ca^,len+1);
|
|
Consts.concat(Tai_string.Create_length_pchar(ca,len+1));
|
|
end
|
|
else
|
|
if is_constcharnode(p) then
|
|
Consts.concat(Tai_string.Create(char(byte(tordconstnode(p).value))+#0))
|
|
else
|
|
Message(cg_e_illegal_expression);
|
|
end
|
|
else
|
|
if p.nodetype=addrn then
|
|
begin
|
|
hp:=taddrnode(p).left;
|
|
while assigned(hp) and (hp.nodetype in [subscriptn,vecn]) do
|
|
hp:=tbinarynode(hp).left;
|
|
if (is_equal(ppointerdef(p.resulttype)^.pointertype.def,ppointerdef(def)^.pointertype.def) or
|
|
(is_equal(ppointerdef(p.resulttype)^.pointertype.def,voiddef)) or
|
|
(is_equal(ppointerdef(def)^.pointertype.def,voiddef))) and
|
|
(hp.nodetype=loadn) then
|
|
begin
|
|
do_firstpass(taddrnode(p).left);
|
|
hp:=taddrnode(p).left;
|
|
offset:=0;
|
|
while assigned(hp) and (hp.nodetype<>loadn) do
|
|
begin
|
|
case hp.nodetype of
|
|
vecn :
|
|
begin
|
|
case tvecnode(hp).left.resulttype^.deftype of
|
|
stringdef :
|
|
begin
|
|
{ this seems OK for shortstring and ansistrings PM }
|
|
{ it is wrong for widestrings !! }
|
|
len:=1;
|
|
base:=0;
|
|
end;
|
|
arraydef :
|
|
begin
|
|
len:=parraydef(tvecnode(hp).left.resulttype)^.elesize;
|
|
base:=parraydef(tvecnode(hp).left.resulttype)^.lowrange;
|
|
end
|
|
else
|
|
Message(cg_e_illegal_expression);
|
|
end;
|
|
if is_constintnode(tvecnode(hp).right) then
|
|
inc(offset,len*(get_ordinal_value(tvecnode(hp).right)-base))
|
|
else
|
|
Message(cg_e_illegal_expression);
|
|
end;
|
|
subscriptn :
|
|
inc(offset,tsubscriptnode(hp).vs^.address)
|
|
else
|
|
Message(cg_e_illegal_expression);
|
|
end;
|
|
hp:=tbinarynode(hp).left;
|
|
end;
|
|
if tloadnode(hp).symtableentry^.typ=constsym then
|
|
Message(type_e_variable_id_expected);
|
|
curconstSegment.concat(Tai_const_symbol.Createname_offset(tloadnode(hp).symtableentry^.mangledname,offset));
|
|
end
|
|
else
|
|
Message(cg_e_illegal_expression);
|
|
end
|
|
else
|
|
{ allow typeof(Object type)}
|
|
if (p.nodetype=inlinen) and
|
|
(tinlinenode(p).inlinenumber=in_typeof_x) then
|
|
begin
|
|
if (tinlinenode(p).left.nodetype=typen) then
|
|
begin
|
|
curconstSegment.concat(Tai_const_symbol.createname(
|
|
pobjectdef(tinlinenode(p).left.resulttype)^.vmt_mangledname));
|
|
end
|
|
else
|
|
Message(cg_e_illegal_expression);
|
|
end
|
|
else
|
|
Message(cg_e_illegal_expression);
|
|
p.free;
|
|
end;
|
|
setdef:
|
|
begin
|
|
p:=comp_expr(true);
|
|
do_firstpass(p);
|
|
if p.nodetype=setconstn then
|
|
begin
|
|
{ we only allow const sets }
|
|
if assigned(tsetconstnode(p).left) then
|
|
Message(cg_e_illegal_expression)
|
|
else
|
|
begin
|
|
{$ifdef i386}
|
|
for l:=0 to def^.size-1 do
|
|
curconstSegment.concat(Tai_const.Create_8bit(tsetconstnode(p).value_set^[l]));
|
|
{$endif}
|
|
{$ifdef m68k}
|
|
j:=0;
|
|
for l:=0 to ((def^.size-1) div 4) do
|
|
{ HORRIBLE HACK because of endian }
|
|
{ now use intel endian for constant sets }
|
|
begin
|
|
curconstSegment.concat(Tai_const.Create_8bit(tordconstnode(p).value_set^[j+3]));
|
|
curconstSegment.concat(Tai_const.Create_8bit(tordconstnode(p).value_set^[j+2]));
|
|
curconstSegment.concat(Tai_const.Create_8bit(tordconstnode(p).value_set^[j+1]));
|
|
curconstSegment.concat(Tai_const.Create_8bit(tordconstnode(p).value_set^[j]));
|
|
Inc(j,4);
|
|
end;
|
|
{$endif}
|
|
end;
|
|
end
|
|
else
|
|
Message(cg_e_illegal_expression);
|
|
p.free;
|
|
end;
|
|
enumdef:
|
|
begin
|
|
p:=comp_expr(true);
|
|
do_firstpass(p);
|
|
if p.nodetype=ordconstn then
|
|
begin
|
|
if is_equal(p.resulttype,def) or
|
|
is_subequal(p.resulttype,def) then
|
|
begin
|
|
case p.resulttype^.size of
|
|
1 : curconstSegment.concat(Tai_const.Create_8bit(tordconstnode(p).value));
|
|
2 : curconstSegment.concat(Tai_const.Create_16bit(tordconstnode(p).value));
|
|
4 : curconstSegment.concat(Tai_const.Create_32bit(tordconstnode(p).value));
|
|
end;
|
|
end
|
|
else
|
|
Message2(type_e_incompatible_types,def^.typename,p.resulttype^.typename);
|
|
end
|
|
else
|
|
Message(cg_e_illegal_expression);
|
|
p.free;
|
|
end;
|
|
stringdef:
|
|
begin
|
|
p:=comp_expr(true);
|
|
do_firstpass(p);
|
|
{ load strval and strlength of the constant tree }
|
|
if p.nodetype=stringconstn then
|
|
begin
|
|
strlength:=tstringconstnode(p).len;
|
|
strval:=tstringconstnode(p).value_str;
|
|
end
|
|
else if is_constcharnode(p) then
|
|
begin
|
|
strval:=pchar(@tordconstnode(p).value);
|
|
strlength:=1
|
|
end
|
|
else if is_constresourcestringnode(p) then
|
|
begin
|
|
strval:=pchar(tpointerord(pconstsym(tloadnode(p).symtableentry)^.value));
|
|
strlength:=pconstsym(tloadnode(p).symtableentry)^.len;
|
|
end
|
|
else
|
|
begin
|
|
Message(cg_e_illegal_expression);
|
|
strlength:=-1;
|
|
end;
|
|
if strlength>=0 then
|
|
begin
|
|
case pstringdef(def)^.string_typ of
|
|
st_shortstring:
|
|
begin
|
|
if strlength>=def^.size then
|
|
begin
|
|
message2(parser_w_string_too_long,strpas(strval),tostr(def^.size-1));
|
|
strlength:=def^.size-1;
|
|
end;
|
|
curconstSegment.concat(Tai_const.Create_8bit(strlength));
|
|
{ this can also handle longer strings }
|
|
getmem(ca,strlength+1);
|
|
move(strval^,ca^,strlength);
|
|
ca[strlength]:=#0;
|
|
curconstSegment.concat(Tai_string.Create_length_pchar(ca,strlength));
|
|
{ fillup with spaces if size is shorter }
|
|
if def^.size>strlength then
|
|
begin
|
|
getmem(ca,def^.size-strlength);
|
|
{ def^.size contains also the leading length, so we }
|
|
{ we have to subtract one }
|
|
fillchar(ca[0],def^.size-strlength-1,' ');
|
|
ca[def^.size-strlength-1]:=#0;
|
|
{ this can also handle longer strings }
|
|
curconstSegment.concat(Tai_string.Create_length_pchar(ca,def^.size-strlength-1));
|
|
end;
|
|
end;
|
|
{$ifdef UseLongString}
|
|
st_longstring:
|
|
begin
|
|
{ first write the maximum size }
|
|
curconstSegment.concat(Tai_const.Create_32bit(strlength))));
|
|
{ fill byte }
|
|
curconstSegment.concat(Tai_const.Create_8bit(0));
|
|
getmem(ca,strlength+1);
|
|
move(strval^,ca^,strlength);
|
|
ca[strlength]:=#0;
|
|
generate_pascii(consts,ca,strlength);
|
|
curconstSegment.concat(Tai_const.Create_8bit(0));
|
|
end;
|
|
{$endif UseLongString}
|
|
st_ansistring:
|
|
begin
|
|
{ an empty ansi string is nil! }
|
|
if (strlength=0) then
|
|
curconstSegment.concat(Tai_const.Create_32bit(0))
|
|
else
|
|
begin
|
|
getdatalabel(ll);
|
|
curconstSegment.concat(Tai_const_symbol.Create(ll));
|
|
{ first write the maximum size }
|
|
Consts.concat(Tai_const.Create_32bit(strlength));
|
|
{ second write the real length }
|
|
Consts.concat(Tai_const.Create_32bit(strlength));
|
|
{ redondent with maxlength but who knows ... (PM) }
|
|
{ third write use count (set to -1 for safety ) }
|
|
Consts.concat(Tai_const.Create_32bit(-1));
|
|
Consts.concat(Tai_label.Create(ll));
|
|
getmem(ca,strlength+2);
|
|
move(strval^,ca^,strlength);
|
|
{ The terminating #0 to be stored in the .data section (JM) }
|
|
ca[strlength]:=#0;
|
|
{ End of the PChar. The memory has to be allocated because in }
|
|
{ tai_string.done, there is a freemem(len+1) (JM) }
|
|
ca[strlength+1]:=#0;
|
|
Consts.concat(Tai_string.Create_length_pchar(ca,strlength+1));
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
p.free;
|
|
end;
|
|
arraydef:
|
|
begin
|
|
if token=_LKLAMMER then
|
|
begin
|
|
consume(_LKLAMMER);
|
|
for l:=parraydef(def)^.lowrange to parraydef(def)^.highrange-1 do
|
|
begin
|
|
readtypedconst(parraydef(def)^.elementtype.def,nil,no_change_allowed);
|
|
consume(_COMMA);
|
|
end;
|
|
readtypedconst(parraydef(def)^.elementtype.def,nil,no_change_allowed);
|
|
consume(_RKLAMMER);
|
|
end
|
|
else
|
|
{ if array of char then we allow also a string }
|
|
if is_char(parraydef(def)^.elementtype.def) then
|
|
begin
|
|
p:=comp_expr(true);
|
|
do_firstpass(p);
|
|
if p.nodetype=stringconstn then
|
|
begin
|
|
len:=tstringconstnode(p).len;
|
|
{ For tp7 the maximum lentgh can be 255 }
|
|
if (m_tp in aktmodeswitches) and
|
|
(len>255) then
|
|
len:=255;
|
|
ca:=tstringconstnode(p).value_str;
|
|
end
|
|
else
|
|
if is_constcharnode(p) then
|
|
begin
|
|
ca:=pchar(@tordconstnode(p).value);
|
|
len:=1;
|
|
end
|
|
else
|
|
begin
|
|
Message(cg_e_illegal_expression);
|
|
len:=0;
|
|
end;
|
|
if len>(Parraydef(def)^.highrange-Parraydef(def)^.lowrange+1) then
|
|
Message(parser_e_string_larger_array);
|
|
for i:=Parraydef(def)^.lowrange to Parraydef(def)^.highrange do
|
|
begin
|
|
if i+1-Parraydef(def)^.lowrange<=len then
|
|
begin
|
|
curconstSegment.concat(Tai_const.Create_8bit(byte(ca^)));
|
|
inc(ca);
|
|
end
|
|
else
|
|
{Fill the remaining positions with #0.}
|
|
curconstSegment.concat(Tai_const.Create_8bit(0));
|
|
end;
|
|
p.free;
|
|
end
|
|
else
|
|
begin
|
|
{ we want the ( }
|
|
consume(_LKLAMMER);
|
|
end;
|
|
end;
|
|
procvardef:
|
|
begin
|
|
{ Procvars and pointers are no longer compatible. }
|
|
{ under tp: =nil or =var under fpc: =nil or =@var }
|
|
if token=_NIL then
|
|
begin
|
|
curconstSegment.concat(Tai_const.Create_32bit(0));
|
|
consume(_NIL);
|
|
exit;
|
|
end
|
|
else
|
|
if not(m_tp_procvar in aktmodeswitches) then
|
|
if token=_KLAMMERAFFE then
|
|
consume(_KLAMMERAFFE);
|
|
getprocvar:=true;
|
|
getprocvardef:=pprocvardef(def);
|
|
p:=comp_expr(true);
|
|
getprocvar:=false;
|
|
do_firstpass(p);
|
|
if codegenerror then
|
|
begin
|
|
p.free;
|
|
exit;
|
|
end;
|
|
{ convert calln to loadn }
|
|
if p.nodetype=calln then
|
|
begin
|
|
if (tcallnode(p).symtableprocentry^.owner^.symtabletype=objectsymtable) and
|
|
is_class(pdef(tcallnode(p).symtableprocentry^.owner^.defowner)) then
|
|
hp:=genloadmethodcallnode(pprocsym(tcallnode(p).symtableprocentry),tcallnode(p).symtableproc,
|
|
tcallnode(p).methodpointer.getcopy)
|
|
else
|
|
hp:=genloadcallnode(pprocsym(tcallnode(p).symtableprocentry),tcallnode(p).symtableproc);
|
|
p.free;
|
|
do_firstpass(hp);
|
|
p:=hp;
|
|
if codegenerror then
|
|
begin
|
|
p.free;
|
|
exit;
|
|
end;
|
|
end
|
|
else if (p.nodetype=addrn) and assigned(taddrnode(p).left) and
|
|
(taddrnode(p).left.nodetype=calln) then
|
|
begin
|
|
if (tcallnode(taddrnode(p).left).symtableprocentry^.owner^.symtabletype=objectsymtable) and
|
|
is_class(pdef(tcallnode(taddrnode(p).left).symtableprocentry^.owner^.defowner)) then
|
|
hp:=genloadmethodcallnode(pprocsym(tcallnode(taddrnode(p).left).symtableprocentry),
|
|
tcallnode(taddrnode(p).left).symtableproc,tcallnode(taddrnode(p).left).methodpointer.getcopy)
|
|
else
|
|
hp:=genloadcallnode(pprocsym(tcallnode(taddrnode(p).left).symtableprocentry),
|
|
tcallnode(taddrnode(p).left).symtableproc);
|
|
p.free;
|
|
do_firstpass(hp);
|
|
p:=hp;
|
|
if codegenerror then
|
|
begin
|
|
p.free;
|
|
exit;
|
|
end;
|
|
end;
|
|
{ let type conversion check everything needed }
|
|
p:=gentypeconvnode(p,def);
|
|
do_firstpass(p);
|
|
if codegenerror then
|
|
begin
|
|
p.free;
|
|
exit;
|
|
end;
|
|
{ remove typeconvn, that will normally insert a lea
|
|
instruction which is not necessary for us }
|
|
if p.nodetype=typeconvn then
|
|
begin
|
|
hp:=ttypeconvnode(p).left;
|
|
ttypeconvnode(p).left:=nil;
|
|
p.free;
|
|
p:=hp;
|
|
end;
|
|
{ remove addrn which we also don't need here }
|
|
if p.nodetype=addrn then
|
|
begin
|
|
hp:=taddrnode(p).left;
|
|
taddrnode(p).left:=nil;
|
|
p.free;
|
|
p:=hp;
|
|
end;
|
|
{ we now need to have a loadn with a procsym }
|
|
if (p.nodetype=loadn) and
|
|
(tloadnode(p).symtableentry^.typ=procsym) then
|
|
begin
|
|
curconstSegment.concat(Tai_const_symbol.createname(
|
|
pprocsym(tloadnode(p).symtableentry)^.definition^.mangledname));
|
|
end
|
|
else
|
|
Message(cg_e_illegal_expression);
|
|
p.free;
|
|
end;
|
|
{ reads a typed constant record }
|
|
recorddef:
|
|
begin
|
|
{ KAZ }
|
|
if (precorddef(def)=rec_tguid) and
|
|
((token=_CSTRING) or (token=_CCHAR) or (token=_ID)) then
|
|
begin
|
|
p:=comp_expr(true);
|
|
p:=gentypeconvnode(p,cshortstringdef);
|
|
do_firstpass(p);
|
|
if p.nodetype=stringconstn then
|
|
begin
|
|
s:=strpas(tstringconstnode(p).value_str);
|
|
p.free;
|
|
if string2guid(s,tmpguid) then
|
|
begin
|
|
curconstSegment.concat(Tai_const.Create_32bit(tmpguid.D1));
|
|
curconstSegment.concat(Tai_const.Create_16bit(tmpguid.D2));
|
|
curconstSegment.concat(Tai_const.Create_16bit(tmpguid.D3));
|
|
for i:=Low(tmpguid.D4) to High(tmpguid.D4) do
|
|
curconstSegment.concat(Tai_const.Create_8bit(tmpguid.D4[i]));
|
|
end
|
|
else
|
|
Message(parser_e_improper_guid_syntax);
|
|
end
|
|
else
|
|
begin
|
|
p.free;
|
|
Message(cg_e_illegal_expression);
|
|
exit;
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
consume(_LKLAMMER);
|
|
aktpos:=0;
|
|
while token<>_RKLAMMER do
|
|
begin
|
|
s:=pattern;
|
|
consume(_ID);
|
|
consume(_COLON);
|
|
srsym:=psym(precorddef(def)^.symtable^.search(s));
|
|
if srsym=nil then
|
|
begin
|
|
Message1(sym_e_id_not_found,s);
|
|
consume_all_until(_SEMICOLON);
|
|
end
|
|
else
|
|
begin
|
|
{ check position }
|
|
if pvarsym(srsym)^.address<aktpos then
|
|
Message(parser_e_invalid_record_const);
|
|
|
|
{ if needed fill }
|
|
if pvarsym(srsym)^.address>aktpos then
|
|
for i:=1 to pvarsym(srsym)^.address-aktpos do
|
|
curconstSegment.concat(Tai_const.Create_8bit(0));
|
|
|
|
{ new position }
|
|
aktpos:=pvarsym(srsym)^.address+pvarsym(srsym)^.vartype.def^.size;
|
|
|
|
{ read the data }
|
|
readtypedconst(pvarsym(srsym)^.vartype.def,nil,no_change_allowed);
|
|
|
|
if token=_SEMICOLON then
|
|
consume(_SEMICOLON)
|
|
else break;
|
|
end;
|
|
end;
|
|
for i:=1 to def^.size-aktpos do
|
|
curconstSegment.concat(Tai_const.Create_8bit(0));
|
|
consume(_RKLAMMER);
|
|
end;
|
|
end;
|
|
{ reads a typed object }
|
|
objectdef:
|
|
begin
|
|
if is_class_or_interface(def) then
|
|
begin
|
|
p:=comp_expr(true);
|
|
do_firstpass(p);
|
|
if p.nodetype<>niln then
|
|
begin
|
|
Message(parser_e_type_const_not_possible);
|
|
consume_all_until(_RKLAMMER);
|
|
end
|
|
else
|
|
begin
|
|
curconstSegment.concat(Tai_const.Create_32bit(0));
|
|
end;
|
|
p.free;
|
|
end
|
|
{ for objects we allow it only if it doesn't contain a vmt }
|
|
else if (oo_has_vmt in pobjectdef(def)^.objectoptions) and
|
|
not(m_tp in aktmodeswitches) then
|
|
Message(parser_e_type_const_not_possible)
|
|
else
|
|
begin
|
|
consume(_LKLAMMER);
|
|
aktpos:=0;
|
|
while token<>_RKLAMMER do
|
|
begin
|
|
s:=pattern;
|
|
consume(_ID);
|
|
consume(_COLON);
|
|
srsym:=nil;
|
|
obj:=pobjectdef(def);
|
|
symt:=obj^.symtable;
|
|
while (srsym=nil) and assigned(symt) do
|
|
begin
|
|
srsym:=psym(symt^.search(s));
|
|
if assigned(obj) then
|
|
obj:=obj^.childof;
|
|
if assigned(obj) then
|
|
symt:=obj^.symtable
|
|
else
|
|
symt:=nil;
|
|
end;
|
|
|
|
if srsym=nil then
|
|
begin
|
|
Message1(sym_e_id_not_found,s);
|
|
consume_all_until(_SEMICOLON);
|
|
end
|
|
else
|
|
begin
|
|
{ check position }
|
|
if pvarsym(srsym)^.address<aktpos then
|
|
Message(parser_e_invalid_record_const);
|
|
|
|
{ check in VMT needs to be added for TP mode }
|
|
if (m_tp in aktmodeswitches) and
|
|
(oo_has_vmt in pobjectdef(def)^.objectoptions) and
|
|
(pobjectdef(def)^.vmt_offset<pvarsym(srsym)^.address) then
|
|
begin
|
|
for i:=1 to pobjectdef(def)^.vmt_offset-aktpos do
|
|
curconstsegment.concat(tai_const.create_8bit(0));
|
|
curconstsegment.concat(tai_const_symbol.createname(pobjectdef(def)^.vmt_mangledname));
|
|
{ this is more general }
|
|
aktpos:=pobjectdef(def)^.vmt_offset + target_os.size_of_pointer;
|
|
end;
|
|
|
|
{ if needed fill }
|
|
if pvarsym(srsym)^.address>aktpos then
|
|
for i:=1 to pvarsym(srsym)^.address-aktpos do
|
|
curconstSegment.concat(Tai_const.Create_8bit(0));
|
|
|
|
{ new position }
|
|
aktpos:=pvarsym(srsym)^.address+pvarsym(srsym)^.vartype.def^.size;
|
|
|
|
{ read the data }
|
|
readtypedconst(pvarsym(srsym)^.vartype.def,nil,no_change_allowed);
|
|
|
|
if token=_SEMICOLON then
|
|
consume(_SEMICOLON)
|
|
else break;
|
|
end;
|
|
end;
|
|
if (m_tp in aktmodeswitches) and
|
|
(oo_has_vmt in pobjectdef(def)^.objectoptions) and
|
|
(pobjectdef(def)^.vmt_offset>=aktpos) then
|
|
begin
|
|
for i:=1 to pobjectdef(def)^.vmt_offset-aktpos do
|
|
curconstsegment.concat(tai_const.create_8bit(0));
|
|
curconstsegment.concat(tai_const_symbol.createname(pobjectdef(def)^.vmt_mangledname));
|
|
{ this is more general }
|
|
aktpos:=pobjectdef(def)^.vmt_offset + target_os.size_of_pointer;
|
|
end;
|
|
for i:=1 to def^.size-aktpos do
|
|
curconstSegment.concat(Tai_const.Create_8bit(0));
|
|
consume(_RKLAMMER);
|
|
end;
|
|
end;
|
|
errordef:
|
|
begin
|
|
{ try to consume something useful }
|
|
if token=_LKLAMMER then
|
|
consume_all_until(_RKLAMMER)
|
|
else
|
|
consume_all_until(_SEMICOLON);
|
|
end;
|
|
else Message(parser_e_type_const_not_possible);
|
|
end;
|
|
end;
|
|
{$ifdef fpc}
|
|
{$maxfpuregisters default}
|
|
{$endif fpc}
|
|
|
|
end.
|
|
{
|
|
$Log$
|
|
Revision 1.16 2001-02-03 00:26:35 peter
|
|
* merged fix for bug 1365
|
|
|
|
Revision 1.15 2000/12/25 00:07:28 peter
|
|
+ new tlinkedlist class (merge of old tstringqueue,tcontainer and
|
|
tlinkedlist objects)
|
|
|
|
Revision 1.14 2000/12/10 20:24:18 peter
|
|
* allow subtypes for enums
|
|
|
|
Revision 1.13 2000/11/29 00:30:38 florian
|
|
* unused units removed from uses clause
|
|
* some changes for widestrings
|
|
|
|
Revision 1.12 2000/11/06 15:54:15 florian
|
|
* fixed two bugs to get make cycle work, but it's not enough
|
|
|
|
Revision 1.11 2000/11/04 14:25:21 florian
|
|
+ merged Attila's changes for interfaces, not tested yet
|
|
|
|
Revision 1.10 2000/10/31 22:02:51 peter
|
|
* symtable splitted, no real code changes
|
|
|
|
Revision 1.9 2000/10/14 10:14:52 peter
|
|
* moehrendorf oct 2000 rewrite
|
|
|
|
Revision 1.8 2000/09/30 13:23:04 peter
|
|
* const array of char and pchar length fixed (merged)
|
|
|
|
Revision 1.7 2000/09/24 15:06:25 peter
|
|
* use defines.inc
|
|
|
|
Revision 1.6 2000/08/27 16:11:52 peter
|
|
* moved some util functions from globals,cobjects to cutils
|
|
* splitted files into finput,fmodule
|
|
|
|
Revision 1.5 2000/08/24 19:13:18 peter
|
|
* allow nil for class typed consts (merged)
|
|
|
|
Revision 1.4 2000/08/16 13:06:06 florian
|
|
+ support of 64 bit integer constants
|
|
|
|
Revision 1.3 2000/08/05 13:25:06 peter
|
|
* packenum 1 fixes (merged)
|
|
|
|
Revision 1.2 2000/07/13 11:32:47 michael
|
|
+ removed logs
|
|
|
|
}
|