3 Copyright (c) 1998-2000 by Florian Klaempfl
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 ****************************************************************************
29 { this procedure reads typed constants }
30 { sym is only needed for ansi strings }
31 { the assembler label is in the middle (PM) }
32 procedure readtypedconst(def
: pdef
;sym
: ptypedconstsym
;no_change_allowed
: boolean);
42 globtype
,systems
,tokens
,
43 cobjects
,globals
,scanner
,
44 symconst
,aasm
,types
,verbose
,
46 { parser specific stuff }
48 { processor specific stuff }
62 { this procedure reads typed constants }
63 procedure readtypedconst(def
: pdef
;sym
: ptypedconstsym
;no_change_allowed
: boolean);
73 curconstsegment
: paasmoutput
;
83 procedure check_range
;
85 if ((p
^.value
>porddef(def
)^.high
) or
86 (p
^.value
<porddef(def
)^.low
)) then
88 if (cs_check_range
in aktlocalswitches
) then
89 Message(parser_e_range_check_error
)
91 Message(parser_w_range_check_error
);
95 (* function is_po_equal(o1,o2:longint):boolean;
97 { assembler does not affect }
98 is_po_equal:=(o1 and not(poassembler))=
99 (o2 and not(poassembler));
102 {$R-} {Range check creates problem with init_8bit(-1) !!}
104 if no_change_allowed
then
105 curconstsegment
:=consts
107 curconstsegment
:=datasegment
;
113 case porddef(def
)^.typ
of
116 if not is_constintnode(p
) then
117 { is't an int expected }
118 Message(cg_e_illegal_expression
)
121 curconstsegment
^.concat(new(pai_const
,init_8bit(p
^.value
)));
126 if not is_constintnode(p
) then
127 Message(cg_e_illegal_expression
)
130 curconstsegment
^.concat(new(pai_const
,init_32bit(p
^.value
)));
135 if not is_constintnode(p
) then
136 Message(cg_e_illegal_expression
)
138 curconstsegment
^.concat(new(pai_const
,init_32bit(p
^.value
)));
141 if not is_constboolnode(p
) then
142 Message(cg_e_illegal_expression
);
143 curconstsegment
^.concat(new(pai_const
,init_8bit(p
^.value
)));
146 if not is_constboolnode(p
) then
147 Message(cg_e_illegal_expression
);
148 curconstsegment
^.concat(new(pai_const
,init_16bit(p
^.value
)));
151 if not is_constboolnode(p
) then
152 Message(cg_e_illegal_expression
);
153 curconstsegment
^.concat(new(pai_const
,init_32bit(p
^.value
)));
156 if not is_constcharnode(p
) then
157 Message(cg_e_illegal_expression
);
158 curconstsegment
^.concat(new(pai_const
,init_8bit(p
^.value
)));
161 if not is_constcharnode(p
) then
162 Message(cg_e_illegal_expression
);
163 curconstsegment
^.concat(new(pai_const
,init_16bit(p
^.value
)));
167 if not is_constintnode(p
) then
168 Message(cg_e_illegal_expression
);
169 curconstsegment
^.concat(new(pai_const
,init_16bit(p
^.value
)));
175 if not is_constintnode(p
) then
176 Message(cg_e_illegal_expression
)
179 {!!!!! hmmm, we can write yet only consts til 2^32-1 :( (FK) }
180 curconstsegment
^.concat(new(pai_const
,init_32bit(p
^.value
)));
181 curconstsegment
^.concat(new(pai_const
,init_32bit(0)));
193 if is_constrealnode(p
) then
195 else if is_constintnode(p
) then
198 Message(cg_e_illegal_expression
);
200 case pfloatdef(def
)^.typ
of
201 s32real
: curconstsegment
^.concat(new(pai_real_32bit
,init(value
)));
202 s64real
: curconstsegment
^.concat(new(pai_real_64bit
,init(value
)));
203 s80real
: curconstsegment
^.concat(new(pai_real_80bit
,init(value
)));
204 s64comp
: curconstsegment
^.concat(new(pai_comp_64bit
,init(value
)));
205 f32bit
: curconstsegment
^.concat(new(pai_const
,init_32bit(trunc(value
*65536))));
206 else internalerror(18);
217 if not(pobjectdef(pclassrefdef(p
^.resulttype
)^.pointertype
.def
)^.is_related(
218 pobjectdef(pclassrefdef(def
)^.pointertype
.def
))) then
219 Message(cg_e_illegal_expression
);
220 curconstsegment
^.concat(new(pai_const_symbol
,init(newasmsymbol(pobjectdef(
221 pclassrefdef(p
^.resulttype
)^.pointertype
.def
)^.vmt_mangledname
))));
224 curconstsegment
^.concat(new(pai_const
,init_32bit(0)));
225 else Message(cg_e_illegal_expression
);
233 if (p
^.treetype
=typeconvn
) and
234 ((p
^.left
^.treetype
=addrn
) or (p
^.left
^.treetype
=niln
)) and
235 is_equal(def
,p
^.resulttype
) then
241 { allows horrible ofs(typeof(TButton)^) code !! }
242 if (p
^.treetype
=addrn
) and (p
^.left
^.treetype
=derefn
) then
250 if p
^.treetype
=niln
then
251 curconstsegment
^.concat(new(pai_const
,init_32bit(0)))
254 if is_char(ppointerdef(def
)^.pointertype
.def
) and
255 (p
^.treetype
<>addrn
) then
258 curconstsegment
^.concat(new(pai_const_symbol
,init(ll
)));
259 consts
^.concat(new(pai_label
,init(ll
)));
260 if p
^.treetype
=stringconstn
then
263 { For tp7 the maximum lentgh can be 255 }
264 if (m_tp
in aktmodeswitches
) and
268 move(p
^.value_str
^,ca
^,len
+1);
269 consts
^.concat(new(pai_string
,init_length_pchar(ca
,len
+1)));
272 if is_constcharnode(p
) then
273 consts
^.concat(new(pai_string
,init(char(byte(p
^.value
))+#0)))
275 Message(cg_e_illegal_expression
);
278 if p
^.treetype
=addrn
then
281 while assigned(hp
) and (hp
^.treetype
in [subscriptn
,vecn
]) do
283 if (is_equal(ppointerdef(p
^.resulttype
)^.pointertype
.def
,ppointerdef(def
)^.pointertype
.def
) or
284 (is_equal(ppointerdef(p
^.resulttype
)^.pointertype
.def
,voiddef
)) or
285 (is_equal(ppointerdef(def
)^.pointertype
.def
,voiddef
))) and
286 (hp
^.treetype
=loadn
) then
288 do_firstpass(p
^.left
);
291 while assigned(hp
) and (hp
^.treetype
<>loadn
) do
296 if (hp
^.left
^.resulttype
^.deftype
=stringdef
) then
298 { this seems OK for shortstring and ansistrings PM }
299 { it is wrong for widestrings !! }
303 else if (hp
^.left
^.resulttype
^.deftype
=arraydef
) then
305 len
:=parraydef(hp
^.left
^.resulttype
)^.elesize
;
306 base
:=parraydef(hp
^.left
^.resulttype
)^.lowrange
;
309 Message(cg_e_illegal_expression
);
310 if is_constintnode(hp
^.right
) then
311 inc(offset
,len
*(get_ordinal_value(hp
^.right
)-base
))
313 Message(cg_e_illegal_expression
);
314 {internalerror(9779);}
317 subscriptn
: inc(offset
,hp
^.vs
^.address
)
319 Message(cg_e_illegal_expression
);
323 if hp
^.symtableentry
^.typ
=constsym
then
324 Message(type_e_variable_id_expected
);
325 curconstsegment
^.concat(new(pai_const_symbol
,initname_offset(hp
^.symtableentry
^.mangledname
,offset
)));
326 (*if token=POINT then
329 while token=_POINT do
332 lsym:=pvarsym(precdef(
333 ppointerdef(p^.resulttype)^.pointertype.def)^.symtable^.search(pattern));
334 if assigned(sym) then
335 offset:=offset+lsym^.address
338 Message1(sym_e_illegal_field,pattern);
342 curconstsegment^.concat(new(pai_const_symbol_offset,init(
343 strpnew(p^.left^.symtableentry^.mangledname),offset)));
347 curconstsegment^.concat(new(pai_const,init_symbol(
348 strpnew(p^.left^.symtableentry^.mangledname))));
352 Message(cg_e_illegal_expression
);
355 { allow typeof(Object type)}
356 if (p
^.treetype
=inlinen
) and
357 (p
^.inlinenumber
=in_typeof_x
) then
359 if (p
^.left
^.treetype
=typen
) then
361 curconstsegment
^.concat(new(pai_const_symbol
,
362 initname(pobjectdef(p
^.left
^.resulttype
)^.vmt_mangledname
)));
365 Message(cg_e_illegal_expression
);
368 Message(cg_e_illegal_expression
);
375 if p
^.treetype
=setconstn
then
377 { we only allow const sets }
378 if assigned(p
^.left
) then
379 Message(cg_e_illegal_expression
)
383 for l
:=0 to def
^.size
-1 do
384 curconstsegment
^.concat(new(pai_const
,init_8bit(p
^.value_set
^[l
])));
388 for l
:=0 to ((def
^.size
-1) div 4) do
389 { HORRIBLE HACK because of endian }
390 { now use intel endian for constant sets }
392 curconstsegment
^.concat(new(pai_const
,init_8bit(p
^.value_set
^[j
+3])));
393 curconstsegment
^.concat(new(pai_const
,init_8bit(p
^.value_set
^[j
+2])));
394 curconstsegment
^.concat(new(pai_const
,init_8bit(p
^.value_set
^[j
+1])));
395 curconstsegment
^.concat(new(pai_const
,init_8bit(p
^.value_set
^[j
])));
402 Message(cg_e_illegal_expression
);
409 if p
^.treetype
=ordconstn
then
411 if is_equal(p
^.resulttype
,def
) or
412 is_subequal(p
^.resulttype
,def
) then
414 case p
^.resulttype
^.size
of
415 1 : curconstsegment
^.concat(new(pai_const
,init_8bit(p
^.value
)));
416 2 : curconstsegment
^.concat(new(pai_const
,init_16bit(p
^.value
)));
417 4 : curconstsegment
^.concat(new(pai_const
,init_32bit(p
^.value
)));
421 Message2(type_e_incompatible_types
,def
^.typename
,p
^.resulttype
^.typename
);
424 Message(cg_e_illegal_expression
);
431 { load strval and strlength of the constant tree }
432 if p
^.treetype
=stringconstn
then
434 strlength
:=p
^.length
;
435 strval
:=p
^.value_str
;
437 else if is_constcharnode(p
) then
439 strval
:=pchar(@p
^.value
);
442 else if is_constresourcestringnode(p
) then
444 strval
:=pchar(pconstsym(p
^.symtableentry
)^.value
);
445 strlength
:=pconstsym(p
^.symtableentry
)^.len
;
449 Message(cg_e_illegal_expression
);
454 case pstringdef(def
)^.string_typ
of
457 if strlength
>=def
^.size
then
459 message2(parser_w_string_too_long
,strpas(strval
),tostr(def
^.size
-1));
460 strlength
:=def
^.size
-1;
462 curconstsegment
^.concat(new(pai_const
,init_8bit(strlength
)));
463 { this can also handle longer strings }
464 getmem(ca
,strlength
+1);
465 move(strval
^,ca
^,strlength
);
467 curconstsegment
^.concat(new(pai_string
,init_length_pchar(ca
,strlength
)));
468 { fillup with spaces if size is shorter }
469 if def
^.size
>strlength
then
471 getmem(ca
,def
^.size
-strlength
);
472 { def^.size contains also the leading length, so we }
473 { we have to subtract one }
474 fillchar(ca
[0],def
^.size
-strlength
-1,' ');
475 ca
[def
^.size
-strlength
-1]:=#0;
476 { this can also handle longer strings }
477 curconstsegment
^.concat(new(pai_string
,init_length_pchar(ca
,def
^.size
-strlength
-1)));
480 {$ifdef UseLongString}
483 { first write the maximum size }
484 curconstsegment
^.concat(new(pai_const
,init_32bit(strlength
)))));
486 curconstsegment
^.concat(new(pai_const
,init_8bit(0)));
487 getmem(ca
,strlength
+1);
488 move(strval
^,ca
^,strlength
);
490 generate_pascii(consts
,ca
,strlength
);
491 curconstsegment
^.concat(new(pai_const
,init_8bit(0)));
493 {$endif UseLongString}
496 { an empty ansi string is nil! }
497 if (strlength
=0) then
498 curconstsegment
^.concat(new(pai_const
,init_32bit(0)))
502 curconstsegment
^.concat(new(pai_const_symbol
,init(ll
)));
503 { first write the maximum size }
504 consts
^.concat(new(pai_const
,init_32bit(strlength
)));
505 { second write the real length }
506 consts
^.concat(new(pai_const
,init_32bit(strlength
)));
507 { redondent with maxlength but who knows ... (PM) }
508 { third write use count (set to -1 for safety ) }
509 consts
^.concat(new(pai_const
,init_32bit(-1)));
510 consts
^.concat(new(pai_label
,init(ll
)));
511 getmem(ca
,strlength
+2);
512 move(strval
^,ca
^,strlength
);
513 { The terminating #0 to be stored in the .data section (JM) }
515 { End of the PChar. The memory has to be allocated because in }
516 { tai_string.done, there is a freemem(len+1) (JM) }
518 consts
^.concat(new(pai_string
,init_length_pchar(ca
,strlength
+1)));
527 if token
=_LKLAMMER
then
530 for l
:=parraydef(def
)^.lowrange
to parraydef(def
)^.highrange
-1 do
532 readtypedconst(parraydef(def
)^.elementtype
.def
,nil,no_change_allowed
);
535 readtypedconst(parraydef(def
)^.elementtype
.def
,nil,no_change_allowed
);
539 { if array of char then we allow also a string }
540 if is_char(parraydef(def
)^.elementtype
.def
) then
544 if p
^.treetype
=stringconstn
then
547 { For tp7 the maximum lentgh can be 255 }
548 if (m_tp
in aktmodeswitches
) and
554 if is_constcharnode(p
) then
556 ca
:=pchar(@p
^.value
);
561 Message(cg_e_illegal_expression
);
564 if len
>(Parraydef(def
)^.highrange
-Parraydef(def
)^.lowrange
+1) then
565 Message(parser_e_string_larger_array
);
566 for i
:=Parraydef(def
)^.lowrange
to Parraydef(def
)^.highrange
do
568 if i
+1-Parraydef(def
)^.lowrange
<=len
then
570 curconstsegment
^.concat(new(pai_const
,init_8bit(byte(ca
^))));
574 {Fill the remaining positions with #0.}
575 curconstsegment
^.concat(new(pai_const
,init_8bit(0)));
587 { Procvars and pointers are no longer compatible. }
588 { under tp: =nil or =var under fpc: =nil or =@var }
591 curconstsegment
^.concat(new(pai_const
,init_32bit(0)));
596 if not(m_tp_procvar
in aktmodeswitches
) then
597 if token
=_KLAMMERAFFE
then
598 consume(_KLAMMERAFFE
);
600 getprocvardef
:=pprocvardef(def
);
609 { convert calln to loadn }
610 if p
^.treetype
=calln
then
612 if (p
^.symtableprocentry
^.owner
^.symtabletype
=objectsymtable
) and
613 (pobjectdef(p
^.symtableprocentry
^.owner
^.defowner
)^.is_class
) then
614 hp
:=genloadmethodcallnode(pprocsym(p
^.symtableprocentry
),p
^.symtableproc
,
615 getcopy(p
^.methodpointer
))
617 hp
:=genloadcallnode(pprocsym(p
^.symtableprocentry
),p
^.symtableproc
);
627 else if (p
^.treetype
=addrn
) and assigned(p
^.left
) and
628 (p
^.left
^.treetype
=calln
) then
630 if (p
^.left
^.symtableprocentry
^.owner
^.symtabletype
=objectsymtable
) and
631 (pobjectdef(p
^.left
^.symtableprocentry
^.owner
^.defowner
)^.is_class
) then
632 hp
:=genloadmethodcallnode(pprocsym(p
^.left
^.symtableprocentry
),
633 p
^.left
^.symtableproc
,getcopy(p
^.left
^.methodpointer
))
635 hp
:=genloadcallnode(pprocsym(p
^.left
^.symtableprocentry
),
636 p
^.left
^.symtableproc
);
646 { let type conversion check everything needed }
647 p
:=gentypeconvnode(p
,def
);
654 { remove typeconvn, that will normally insert a lea
655 instruction which is not necessary for us }
656 if p
^.treetype
=typeconvn
then
662 { remove addrn which we also don't need here }
663 if p
^.treetype
=addrn
then
669 { we now need to have a loadn with a procsym }
670 if (p
^.treetype
=loadn
) and
671 (p
^.symtableentry
^.typ
=procsym
) then
673 curconstsegment
^.concat(new(pai_const_symbol
,
674 initname(pprocsym(p
^.symtableentry
)^.definition
^.mangledname
)));
677 Message(cg_e_illegal_expression
);
680 { reads a typed constant record }
685 while token
<>_RKLAMMER
do
690 srsym
:=precorddef(def
)^.symtable
^.search(s
);
693 Message1(sym_e_id_not_found
,s
);
694 consume_all_until(_SEMICOLON
);
699 if pvarsym(srsym
)^.address
<aktpos
then
700 Message(parser_e_invalid_record_const
);
703 if pvarsym(srsym
)^.address
>aktpos
then
704 for i
:=1 to pvarsym(srsym
)^.address
-aktpos
do
705 curconstsegment
^.concat(new(pai_const
,init_8bit(0)));
708 aktpos
:=pvarsym(srsym
)^.address
+pvarsym(srsym
)^.vartype
.def
^.size
;
711 readtypedconst(pvarsym(srsym
)^.vartype
.def
,nil,no_change_allowed
);
713 if token
=_SEMICOLON
then
718 for i
:=1 to def
^.size
-aktpos
do
719 curconstsegment
^.concat(new(pai_const
,init_8bit(0)));
722 { reads a typed object }
725 if ([oo_has_vmt
,oo_is_class
]*pobjectdef(def
)^.objectoptions
)<>[] then
727 { support nil assignment for classes }
728 if pobjectdef(def
)^.is_class
and
729 try_to_consume(_NIL
) then
731 curconstsegment
^.concat(new(pai_const
,init_32bit(0)));
735 Message(parser_e_type_const_not_possible
);
736 consume_all_until(_RKLAMMER
);
743 while token
<>_RKLAMMER
do
749 obj
:=pobjectdef(def
);
751 while (srsym
=nil) and assigned(symt
) do
753 srsym
:=symt
^.search(s
);
754 if assigned(obj
) then
756 if assigned(obj
) then
764 Message1(sym_e_id_not_found
,s
);
765 consume_all_until(_SEMICOLON
);
770 if pvarsym(srsym
)^.address
<aktpos
then
771 Message(parser_e_invalid_record_const
);
774 if pvarsym(srsym
)^.address
>aktpos
then
775 for i
:=1 to pvarsym(srsym
)^.address
-aktpos
do
776 curconstsegment
^.concat(new(pai_const
,init_8bit(0)));
779 aktpos
:=pvarsym(srsym
)^.address
+pvarsym(srsym
)^.vartype
.def
^.size
;
782 readtypedconst(pvarsym(srsym
)^.vartype
.def
,nil,no_change_allowed
);
784 if token
=_SEMICOLON
then
789 for i
:=1 to def
^.size
-aktpos
do
790 curconstsegment
^.concat(new(pai_const
,init_8bit(0)));
796 { try to consume something useful }
797 if token
=_LKLAMMER
then
798 consume_all_until(_RKLAMMER
)
800 consume_all_until(_SEMICOLON
);
802 else Message(parser_e_type_const_not_possible
);
806 {$maxfpuregisters default}
812 Revision 1.1 2002/02/19 08:23:37 sasu
815 Revision 1.1.2.4 2000/12/10 20:15:59 peter
816 * also check for subtypes for enumerations
818 Revision 1.1.2.3 2000/09/30 13:12:32 peter
819 * const array of char and pchar length fixed
821 Revision 1.1.2.2 2000/08/24 19:10:51 peter
822 * allow nil for class typed consts
824 Revision 1.1.2.1 2000/08/05 13:21:52 peter
825 * fixed enumwriting with enumsize <> 4
827 Revision 1.1 2000/07/13 06:29:55 michael
830 Revision 1.68 2000/06/06 13:06:17 jonas
831 * ansistring constants now also get a trailing #0 (bug reported by
834 Revision 1.67 2000/05/17 17:10:06 peter
835 * add support for loading of typed const strings with resourcestrings,
836 made the loading also a bit more generic
838 Revision 1.66 2000/05/12 06:02:01 pierre
839 * * get it to compile with Delphi by Kovacs Attila Zoltan
841 Revision 1.65 2000/05/11 09:15:15 pierre
842 + add a warning if a const string is longer than the
843 length of the string type
845 Revision 1.64 2000/04/02 09:12:51 florian
846 + constant procedure variables can have a @ in front:
847 const p : procedure = @p;
849 const p : procedure = p;
852 Revision 1.63 2000/02/13 14:21:51 jonas
853 * modifications to make the compiler functional when compiled with
856 Revision 1.62 2000/02/09 13:23:01 peter
859 Revision 1.61 2000/01/07 01:14:33 peter
860 * updated copyright to 2000
862 Revision 1.60 1999/12/18 14:55:21 florian
863 * very basic widestring support
865 Revision 1.59 1999/11/30 10:40:51 peter
868 Revision 1.58 1999/11/08 18:50:11 florian
869 * disposetree for classrefdef added
871 Revision 1.57 1999/11/08 16:24:28 pierre
872 * missing disposetree added to avoid memory loss
874 Revision 1.56 1999/11/08 14:02:16 florian
875 * problem with "index X"-properties solved
876 * typed constants of class references are now allowed
878 Revision 1.55 1999/11/06 14:34:23 peter
879 * truncated log to 20 revs
881 Revision 1.54 1999/10/14 14:57:54 florian
882 - removed the hcodegen use in the new cg, use cgbase instead
884 Revision 1.53 1999/09/26 21:30:20 peter
885 + constant pointer support which can happend with typecasting like
887 * better procvar parsing in typed consts
889 Revision 1.52 1999/08/10 12:30:02 pierre
890 * avoid unused locals
892 Revision 1.51 1999/08/04 13:03:02 jonas
893 * all tokens now start with an underscore
896 Revision 1.50 1999/08/04 00:23:21 florian
897 * renamed i386asm and i386base to cpuasm and cpubase
899 Revision 1.49 1999/08/03 22:03:08 peter
900 * moved bitmask constants to sets
901 * some other type/const renamings
903 Revision 1.48 1999/07/23 16:05:26 peter
904 * alignment is now saved in the symtable
905 * C alignment added for records
906 * PPU version increased to solve .12 <-> .13 probs