3 Copyright (c) 1998-2000 by Florian Klaempfl
5 Does the parsing of the statements
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 ****************************************************************************
34 function block(islibrary
: boolean) : ptree
;
36 { reads an assembler block }
37 function assembler_block
: ptree
;
42 globtype
,systems
,tokens
,
43 strings
,cobjects
,globals
,files
,verbose
,
44 symconst
,symtable
,aasm
,pass_1
,types
,scanner
,
51 ,pbase
,pexpr
,pdecl
,cpubase
,cpuasm
71 ,tgeni386
{ this is a dummy!! }
74 ,tgeni386
{ this is a dummy!! }
80 statement_level
: longint = 0;
82 function statement
: ptree
;forward;
85 function if_statement
: ptree
;
87 ex
,if_a
,else_a
: ptree
;
97 if try_to_consume(_ELSE
) then
101 if_statement
:=genloopnode(ifn
,ex
,if_a
,else_a
,false);
104 { creates a block (list) of statements, til the next END token }
105 function statements_til_end
: ptree
;
116 last
:=gennode(statementn
,nil,statement
);
121 last
^.left
:=gennode(statementn
,nil,statement
);
124 if not try_to_consume(_SEMICOLON
) then
129 statements_til_end
:=gensinglenode(blockn
,first
);
132 function case_statement
: ptree
;
135 { contains the label number of currently parsed case block }
136 aktcaselabel
: pasmlabel
;
137 firstlabel
: boolean;
140 { the typ of the case expression }
143 procedure newcaselabel(l
,h
: longint;first
:boolean);
146 hcaselabel
: pcaserecord
;
148 procedure insertlabel(var p
: pcaserecord
);
151 if p
=nil then p
:=hcaselabel
153 if (p
^._low
>hcaselabel
^._low
) and
154 (p
^._low
>hcaselabel
^._high
) then
155 if (hcaselabel
^.statement
= p
^.statement
) and
156 (p
^._low
= hcaselabel
^._high
+ 1) then
158 p
^._low
:= hcaselabel
^._low
;
164 if (p
^._high
<hcaselabel
^._low
) and
165 (p
^._high
<hcaselabel
^._high
) then
166 if (hcaselabel
^.statement
= p
^.statement
) and
167 (p
^._high
+1 = hcaselabel
^._low
) then
169 p
^._high
:= hcaselabel
^._high
;
173 insertlabel(p
^.greater
)
174 else Message(parser_e_double_caselabel
);
179 hcaselabel
^.less
:=nil;
180 hcaselabel
^.greater
:=nil;
181 hcaselabel
^.statement
:=aktcaselabel
;
182 hcaselabel
^.firstlabel
:=first
;
183 getlabel(hcaselabel
^._at
);
185 hcaselabel
^._high
:=h
;
190 code
,caseexpr
,p
,instruc
,elseblock
: ptree
;
192 casedeferror
: boolean;
195 caseexpr
:=comp_expr(true);
196 { determines result type }
198 do_firstpass(caseexpr
);
200 casedef
:=caseexpr
^.resulttype
;
201 if (not assigned(casedef
)) or
202 not(is_ordinal(casedef
) or is_64bitint(casedef
)) then
204 CGMessage(type_e_ordinal_expr_expected
);
205 { create a correct tree }
206 disposetree(caseexpr
);
207 caseexpr
:=genordinalconstnode(0,u32bitdef
);
208 { set error flag so no rangechecks are done }
213 inc(statement_level
);
217 getlabel(aktcaselabel
);
220 { may be an instruction has more case labels }
227 if (p
^.treetype
=rangen
) then
229 { type checking for case statements }
230 if is_subequal(casedef
, p
^.left
^.resulttype
) and
231 is_subequal(casedef
, p
^.right
^.resulttype
) then
233 hl1
:=get_ordinal_value(p
^.left
);
234 hl2
:=get_ordinal_value(p
^.right
);
236 CGMessage(parser_e_case_lower_less_than_upper_bound
);
237 if not casedeferror
then
239 testrange(casedef
,hl1
);
240 testrange(casedef
,hl2
);
244 CGMessage(parser_e_case_mismatch
);
245 newcaselabel(hl1
,hl2
,firstlabel
);
249 { type checking for case statements }
250 if not is_subequal(casedef
, p
^.resulttype
) then
251 CGMessage(parser_e_case_mismatch
);
252 hl1
:=get_ordinal_value(p
);
253 if not casedeferror
then
254 testrange(casedef
,hl1
);
255 newcaselabel(hl1
,hl1
,firstlabel
);
266 { handles instruction block }
267 p
:=gensinglenode(labeln
,statement
);
268 p
^.labelnr
:=aktcaselabel
;
270 { concats instruction }
271 instruc
:=gennode(statementn
,instruc
,p
);
273 if not((token
=_ELSE
) or (token
=_OTHERWISE
) or (token
=_END
)) then
275 until (token
=_ELSE
) or (token
=_OTHERWISE
) or (token
=_END
);
277 if (token
=_ELSE
) or (token
=_OTHERWISE
) then
279 if not try_to_consume(_ELSE
) then
281 elseblock
:=statements_til_end
;
288 dec(statement_level
);
290 code
:=gencasenode(caseexpr
,instruc
,root
);
292 code
^.elseblock
:=elseblock
;
294 case_statement
:=code
;
298 function repeat_statement
: ptree
;
301 first
,last
,p_e
: ptree
;
306 inc(statement_level
);
308 while token
<>_UNTIL
do
312 last
:=gennode(statementn
,nil,statement
);
317 last
^.left
:=gennode(statementn
,nil,statement
);
320 if not try_to_consume(_SEMICOLON
) then
325 dec(statement_level
);
327 first
:=gensinglenode(blockn
,first
);
328 p_e
:=comp_expr(true);
329 repeat_statement
:=genloopnode(repeatn
,p_e
,first
,nil,false);
333 function while_statement
: ptree
;
340 p_e
:=comp_expr(true);
343 while_statement
:=genloopnode(whilen
,p_e
,p_a
,nil,false);
347 function for_statement
: ptree
;
350 p_e
,tovalue
,p_a
: ptree
;
354 { parse loop header }
357 if token
=_DOWNTO
then
367 tovalue
:=comp_expr(true);
370 { ... now the instruction }
372 for_statement
:=genloopnode(forn
,p_e
,tovalue
,p_a
,backward
);
376 function _with_statement
: ptree
;
380 i
,levelcount
: longint;
381 withsymtable
,symtab
: psymtable
;
389 set_varstate(p
,false);
391 if (not codegenerror
) and
392 (p
^.resulttype
^.deftype
in [objectdef
,recorddef
]) then
394 case p
^.resulttype
^.deftype
of
396 obj
:=pobjectdef(p
^.resulttype
);
397 withsymtable
:=new(pwithsymtable
,init
);
398 withsymtable
^.symsearch
:=obj
^.symtable
^.symsearch
;
399 withsymtable
^.defowner
:=obj
;
400 symtab
:=withsymtable
;
401 if (p
^.treetype
=loadn
) and
402 (p
^.symtable
=aktprocsym
^.definition
^.localst
) then
403 pwithsymtable(symtab
)^.direct_with
:=true;
404 {symtab^.withnode:=p; not yet allocated !! }
405 pwithsymtable(symtab
)^.withrefnode
:=p
;
408 while assigned(obj
) do
410 symtab
^.next
:=new(pwithsymtable
,init
);
411 symtab
:=symtab
^.next
;
412 symtab
^.symsearch
:=obj
^.symtable
^.symsearch
;
413 if (p
^.treetype
=loadn
) and
414 (p
^.symtable
=aktprocsym
^.definition
^.localst
) then
415 pwithsymtable(symtab
)^.direct_with
:=true;
416 {symtab^.withnode:=p; not yet allocated !! }
417 pwithsymtable(symtab
)^.withrefnode
:=p
;
418 symtab
^.defowner
:=obj
;
422 symtab
^.next
:=symtablestack
;
423 symtablestack
:=withsymtable
;
426 symtab
:=precorddef(p
^.resulttype
)^.symtable
;
428 withsymtable
:=new(pwithsymtable
,init
);
429 withsymtable
^.symsearch
:=symtab
^.symsearch
;
430 withsymtable
^.next
:=symtablestack
;
431 if (p
^.treetype
=loadn
) and
432 (p
^.symtable
=aktprocsym
^.definition
^.localst
) then
433 pwithsymtable(withsymtable
)^.direct_with
:=true;
434 {symtab^.withnode:=p; not yet allocated !! }
435 pwithsymtable(withsymtable
)^.withrefnode
:=p
;
436 withsymtable
^.defowner
:=precorddef(p
^.resulttype
);
437 symtablestack
:=withsymtable
;
443 right
:=_with_statement
{$ifndef tp}(){$endif};
448 if token
<>_SEMICOLON
then
453 for i
:=1 to levelcount
do
454 symtablestack
:=symtablestack
^.next
;
455 _with_statement
:=genwithnode(pwithsymtable(withsymtable
),p
,right
,levelcount
);
459 Message(parser_e_false_with_expr
);
460 { try to recover from error }
474 if token
<>_SEMICOLON
then
477 _with_statement
:=nil;
482 function with_statement
: ptree
;
485 with_statement
:=_with_statement
;
489 function raise_statement
: ptree
;
492 p
,pobj
,paddr
,pframe
: ptree
;
499 if not(token
in [_SEMICOLON
,_END
]) then
502 pobj
:=comp_expr(true);
503 if try_to_consume(_AT
) then
505 paddr
:=comp_expr(true);
506 if try_to_consume(_COMMA
) then
507 pframe
:=comp_expr(true);
512 if (block_type
<>bt_except
) then
513 Message(parser_e_no_reraise_possible
);
515 p
:=genraisenode(pobj
,paddr
,pframe
);
520 function try_statement
: ptree
;
523 p_try_block
,p_finally_block
,first
,last
,
524 p_default
,p_specific
,hp
: ptree
;
527 old_block_type
: tblock_type
;
528 exceptsymtable
: psymtable
;
532 procinfo
^.flags
:=procinfo
^.flags
or
538 { read statements to try }
541 inc(statement_level
);
543 while (token
<>_FINALLY
) and (token
<>_EXCEPT
) do
547 last
:=gennode(statementn
,nil,statement
);
552 last
^.left
:=gennode(statementn
,nil,statement
);
555 if not try_to_consume(_SEMICOLON
) then
559 p_try_block
:=gensinglenode(blockn
,first
);
561 if try_to_consume(_FINALLY
) then
563 p_finally_block
:=statements_til_end
;
564 try_statement
:=gennode(tryfinallyn
,p_try_block
,p_finally_block
);
565 dec(statement_level
);
571 old_block_type
:=block_type
;
572 block_type
:=bt_except
;
573 ot
:=pobjectdef(generrordef
);
576 { catch specific exceptions }
583 getsym(objname
,false);
585 { is a explicit name for the exception given ? }
586 if try_to_consume(_COLON
) then
588 getsym(pattern
,true);
590 if srsym
^.typ
=unitsym
then
593 getsymonlyin(punitsym(srsym
)^.unitsymtable
,pattern
);
596 if (srsym
^.typ
=typesym
) and
597 (ptypesym(srsym
)^.restype
.def
^.deftype
=objectdef
) and
598 pobjectdef(ptypesym(srsym
)^.restype
.def
)^.is_class
then
600 ot
:=pobjectdef(ptypesym(srsym
)^.restype
.def
);
601 sym
:=new(pvarsym
,initdef(objname
,ot
));
605 sym
:=new(pvarsym
,initdef(objname
,new(perrordef
,init
)));
606 if (srsym
^.typ
=typesym
) then
607 Message1(type_e_class_type_expected
,ptypesym(srsym
)^.restype
.def
^.typename
)
609 Message1(type_e_class_type_expected
,ot
^.typename
);
611 exceptsymtable
:=new(psymtable
,init(stt_exceptsymtable
));
612 exceptsymtable
^.insert(sym
);
613 { insert the exception symtable stack }
614 exceptsymtable
^.next
:=symtablestack
;
615 symtablestack
:=exceptsymtable
;
619 { check if type is valid, must be done here because
620 with "e: Exception" the e is not necessary }
623 Message1(sym_e_id_not_found
,objname
);
626 { only exception type }
627 if srsym
^.typ
=unitsym
then
630 getsymonlyin(punitsym(srsym
)^.unitsymtable
,pattern
);
633 if (srsym
^.typ
=typesym
) and
634 (ptypesym(srsym
)^.restype
.def
^.deftype
=objectdef
) and
635 pobjectdef(ptypesym(srsym
)^.restype
.def
)^.is_class
then
636 ot
:=pobjectdef(ptypesym(srsym
)^.restype
.def
)
639 ot
:=pobjectdef(generrordef
);
640 if (srsym
^.typ
=typesym
) then
641 Message1(type_e_class_type_expected
,ptypesym(srsym
)^.restype
.def
^.typename
)
643 Message1(type_e_class_type_expected
,ot
^.typename
);
651 hp
:=gennode(onn
,nil,statement
);
652 if ot
^.deftype
=errordef
then
655 hp
:=genzeronode(errorn
);
657 if p_specific
=nil then
667 { set the informations }
668 if last
^.treetype
= onn
then
670 last
^.excepttype
:=ot
;
671 last
^.exceptsymtable
:=exceptsymtable
;
672 last
^.disposetyp
:=dt_onn
;
674 { remove exception symtable }
675 if assigned(exceptsymtable
) then
678 if last
^.treetype
<> onn
then
679 dispose(exceptsymtable
,done
);
681 if not try_to_consume(_SEMICOLON
) then
684 until (token
=_END
) or(token
=_ELSE
);
686 { catch the other exceptions }
689 p_default
:=statements_til_end
;
695 { catch all exceptions }
697 p_default
:=statements_til_end
;
699 dec(statement_level
);
701 block_type
:=old_block_type
;
702 try_statement
:=genloopnode(tryexceptn
,p_try_block
,p_specific
,p_default
,false);
707 function exit_statement
: ptree
;
714 if try_to_consume(_LKLAMMER
) then
718 if (block_type
=bt_except
) then
719 Message(parser_e_exit_with_argument_not__possible
);
720 if procinfo
^.returntype
.def
=pdef(voiddef
) then
721 Message(parser_e_void_function
);
725 p
:=gensinglenode(exitn
,p
);
726 // p^.resulttype:=procinfo^.returntype.def;
727 p
^.resulttype
:=voiddef
;
732 function _asm_statement
: ptree
;
737 Inside_asm_statement:=true
;
739 asmmode_none
: ; { just be there to allow to a compile without
740 any assembler readers }
744 asmstat:=ra386att.assemble
;
748 asmstat:=ra386int.assemble
;
753 if
not target_asm.allowdirect then
754 Message
(parser_f_direct_assembler_not_allowed
);
755 if
(pocall_inline
in aktprocsym^.definition^.proccalloptions
) then
757 Message1
(parser_w_not_supported_for_inline
,'direct asm');
758 Message
(parser_w_inlining_disabled
);
760 exclude
(aktprocsym^.definition^.proccalloptions
,pocall_inline
);
762 aktprocsym^.definition^.
proccalloptions:=aktprocsym^.definition^.proccalloptions
-[pocall_inline
];
765 asmstat:=ra386dir.assemble
;
772 asmstat:=ra68kmot.assemble
;
776 Message
(parser_f_assembler_reader_not_supported
);
779 { Read first the _ASM statement }
784 if try_to_consume(_LECKKLAMMER
) then
786 { it's possible to specify the modified registers }
787 asmstat^.
object_preserved:=true
;
788 if token
<>_RECKKLAMMER then
790 { uppercase, because it's a CSTRING }
793 if pattern
='EAX' then
794 usedinproc:=usedinproc
or ($80 shr byte(R_EAX
))
795 else if pattern
='EBX' then
796 usedinproc:=usedinproc
or ($80 shr byte(R_EBX
))
797 else if pattern
='ECX' then
798 usedinproc:=usedinproc
or ($80 shr byte(R_ECX
))
799 else if pattern
='EDX' then
800 usedinproc:=usedinproc
or ($80 shr byte(R_EDX
))
801 else if pattern
='ESI' then
803 usedinproc:=usedinproc
or ($80 shr byte(R_ESI
));
804 asmstat^.
object_preserved:=false
;
806 else if pattern
='EDI' then
807 usedinproc:=usedinproc
or ($80 shr byte(R_EDI
))
811 usedinproc:=usedinproc
or ($800 shr word(R_D0
))
812 else if pattern
='D1' then
813 usedinproc:=usedinproc
or ($800 shr word(R_D1
))
814 else if pattern
='D6' then
815 usedinproc:=usedinproc
or ($800 shr word(R_D6
))
816 else if pattern
='A0' then
817 usedinproc:=usedinproc
or ($800 shr word(R_A0
))
818 else if pattern
='A1' then
819 usedinproc:=usedinproc
or ($800 shr word(R_A1
))
821 else consume
(_RECKKLAMMER
);
823 if
not try_to_consume
(_COMMA
) then
826 consume
(_RECKKLAMMER
);
828 else
usedinproc:=$ff;
831 { mark the start and the end of the assembler block for the optimizer }
833 If Assigned
(AsmStat^.p_asm
) Then
835 Marker
:= New
(Pai_Marker
, Init
(AsmBlockStart
));
836 AsmStat^.p_asm^.Insert
(Marker
);
837 Marker
:= New
(Pai_Marker
, Init
(AsmBlockEnd
));
838 AsmStat^.p_asm^.Concat
(Marker
);
840 Inside_asm_statement:=false
;
842 _asm_statement:=asmstat
;
846 function new_dispose_statement
: ptree
;
850 again
: boolean; { dummy for do_proc_call }
851 destructorname
: stringid
;
855 destructorpos
,storepos
: tfileposinfo
;
859 if try_to_consume(_NEW
) then
874 set_varstate(p
,tt
=hdisposen
);
878 new(o,init); (*Also a valid new statement*)
881 if try_to_consume(_COMMA
) then
883 { extended syntax of new and dispose }
884 { function styled new is handled in factor }
885 { destructors have no parameters }
886 destructorname
:=pattern
;
887 destructorpos
:=tokenpos
;
894 if (pd
^.deftype
<>pointerdef
) then
896 Message1(type_e_pointer_type_expected
,pd
^.typename
);
899 new_dispose_statement
:=genzeronode(errorn
);
902 { first parameter must be an object or class }
903 if ppointerdef(pd
)^.pointertype
.def
^.deftype
<>objectdef
then
905 Message(parser_e_pointer_to_class_expected
);
906 new_dispose_statement
:=factor(false);
907 consume_all_until(_RKLAMMER
);
911 { check, if the first parameter is a pointer to a _class_ }
912 classh
:=pobjectdef(ppointerdef(pd
)^.pointertype
.def
);
913 if classh
^.is_class
then
915 Message(parser_e_no_new_or_dispose_for_classes
);
916 new_dispose_statement
:=factor(false);
917 consume_all_until(_RKLAMMER
);
921 { search cons-/destructor, also in parent classes }
923 tokenpos
:=destructorpos
;
924 sym
:=search_class_member(classh
,destructorname
);
927 { the second parameter of new/dispose must be a call }
928 { to a cons-/destructor }
929 if (not assigned(sym
)) or (sym
^.typ
<>procsym
) then
932 Message(parser_e_expr_have_to_be_constructor_call
)
934 Message(parser_e_expr_have_to_be_destructor_call
);
935 new_dispose_statement
:=genzeronode(errorn
);
939 p2
:=gensinglenode(tt
,p
);
942 { Constructors can take parameters.}
943 p2
^.resulttype
:=ppointerdef(pd
)^.pointertype
.def
;
944 do_member_read(false,sym
,p2
,pd
,again
);
948 if (m_tp
in aktmodeswitches
) then
950 { Constructors can take parameters.}
951 p2
^.resulttype
:=ppointerdef(pd
)^.pointertype
.def
;
952 do_member_read(false,sym
,p2
,pd
,again
);
956 p2
:=genmethodcallnode(pprocsym(sym
),srsymtable
,p2
);
957 { support dispose(p,done()); }
958 if try_to_consume(_LKLAMMER
) then
960 if not try_to_consume(_RKLAMMER
) then
962 Message(parser_e_no_paras_for_destructor
);
963 consume_all_until(_RKLAMMER
);
970 { we need the real called method }
974 if not codegenerror
then
976 if (ht
=_NEW
) and (p2
^.procdefinition
^.proctypeoption
<>potype_constructor
) then
977 Message(parser_e_expr_have_to_be_constructor_call
);
978 if (ht
=_DISPOSE
) and (p2
^.procdefinition
^.proctypeoption
<>potype_destructor
) then
979 Message(parser_e_expr_have_to_be_destructor_call
);
983 p2
:=gennode(assignn
,getcopy(p
),gensinglenode(newn
,p2
));
984 p2
^.right
^.resulttype
:=pd2
;
987 new_dispose_statement
:=p2
;
992 if p
^.resulttype
=nil then
993 p
^.resulttype
:=generrordef
;
994 if (p
^.resulttype
^.deftype
<>pointerdef
) then
996 Message1(type_e_pointer_type_expected
,p
^.resulttype
^.typename
);
997 new_dispose_statement
:=genzeronode(errorn
);
1001 if (ppointerdef(p
^.resulttype
)^.pointertype
.def
^.deftype
=objectdef
) and
1002 (oo_has_vmt
in pobjectdef(ppointerdef(p
^.resulttype
)^.pointertype
.def
)^.objectoptions
) then
1003 Message(parser_w_use_extended_syntax_for_objects
);
1004 if (ppointerdef(p
^.resulttype
)^.pointertype
.def
^.deftype
=orddef
) and
1005 (porddef(ppointerdef(p
^.resulttype
)^.pointertype
.def
)^.typ
=uvoid
) then
1006 if (m_tp
in aktmodeswitches
) or
1007 (m_delphi
in aktmodeswitches
) then
1008 Message(parser_w_no_new_dispose_on_void_pointers
)
1010 Message(parser_e_no_new_dispose_on_void_pointers
);
1013 _NEW
: new_dispose_statement
:=gensinglenode(simplenewn
,p
);
1014 _DISPOSE
: new_dispose_statement
:=gensinglenode(simpledisposen
,p
);
1022 function statement_block(starttoken
: ttoken
) : ptree
;
1026 filepos
: tfileposinfo
;
1031 consume(starttoken
);
1032 inc(statement_level
);
1034 while not(token
in [_END
,_FINALIZATION
]) do
1038 last
:=gennode(statementn
,nil,statement
);
1043 last
^.left
:=gennode(statementn
,nil,statement
);
1046 if (token
in [_END
,_FINALIZATION
]) then
1050 { if no semicolon, then error and go on }
1051 if token
<>_SEMICOLON
then
1053 consume(_SEMICOLON
);
1054 consume_all_until(_SEMICOLON
);
1056 consume(_SEMICOLON
);
1061 { don't consume the finalization token, it is consumed when
1062 reading the finalization block, but allow it only after
1063 an initalization ! }
1064 if (starttoken
<>_INITIALIZATION
) or (token
<>_FINALIZATION
) then
1067 dec(statement_level
);
1069 last
:=gensinglenode(blockn
,first
);
1070 set_tree_filepos(last
,filepos
);
1071 statement_block
:=last
;
1075 function statement
: ptree
;
1080 labelnr
: pasmlabel
;
1081 filepos
: tfileposinfo
;
1091 if not(cs_support_goto
in aktmoduleswitches
)then
1092 Message(sym_e_goto_and_label_not_supported
);
1094 if (token
<>_INTCONST
) and (token
<>_ID
) then
1096 Message(sym_e_label_not_found
);
1097 code
:=genzeronode(errorn
);
1101 getsym(pattern
,true);
1103 if srsym
^.typ
<>labelsym
then
1105 Message(sym_e_id_is_no_label_id
);
1106 code
:=genzeronode(errorn
);
1110 code
:=genlabelnode(goton
,plabelsym(srsym
)^.lab
);
1111 code
^.labsym
:=plabelsym(srsym
);
1112 { set flag that this label is used }
1113 plabelsym(srsym
)^.used
:=true;
1117 _BEGIN
: code
:=statement_block(_BEGIN
);
1118 _IF
: code
:=if_statement
;
1119 _CASE
: code
:=case_statement
;
1120 _REPEAT
: code
:=repeat_statement
;
1121 _WHILE
: code
:=while_statement
;
1122 _FOR
: code
:=for_statement
;
1123 _NEW
,_DISPOSE
: code
:=new_dispose_statement
;
1125 _WITH
: code
:=with_statement
;
1126 _TRY
: code
:=try_statement
;
1127 _RAISE
: code
:=raise_statement
;
1128 { semicolons,else until and end are ignored }
1133 code
:=genzeronode(niln
);
1135 { internalerror(100); }
1136 if (aktprocsym
^.definition
^.proctypeoption
<>potype_constructor
) then
1137 Message(parser_e_fail_only_in_constructor
);
1139 code
:=genzeronode(failn
);
1141 _EXIT
: code
:=exit_statement
;
1143 code
:=_asm_statement
;
1146 Message(scan_f_end_of_file
);
1150 if (token
in [_INTCONST
,_ID
]) then
1152 getsym(pattern
,true);
1155 { it is NOT necessarily the owner
1156 it can be a withsymtable !!! }
1157 lastsrsymtable
:=srsymtable
;
1158 if assigned(srsym
) and (srsym
^.typ
=labelsym
) then
1162 { we must preserve srsym to set code later }
1163 sr
:=plabelsym(srsym
);
1165 Message(sym_e_label_already_defined
);
1168 { statement modifies srsym }
1170 lastsymknown
:=false;
1171 { the pointer to the following instruction }
1172 { isn't a very clean way }
1173 code
:=gensinglenode(labeln
,statement
{$ifndef tp}(){$endif});
1174 code
^.labelnr
:=labelnr
;
1176 { sorry, but there is a jump the easiest way }
1181 if not(p
^.treetype
in [calln
,assignn
,breakn
,inlinen
,
1183 Message(cg_e_illegal_expression
);
1184 { specify that we don't use the value returned by the call }
1185 { Question : can this be also improtant
1188 - dispose of temp stack space
1189 - dispose on FPU stack }
1190 if p
^.treetype
=calln
then
1191 p
^.return_value_used
:=false;
1196 if assigned(code
) then
1197 set_tree_filepos(code
,filepos
);
1201 function block(islibrary
: boolean) : ptree
;
1204 funcretsym
: pfuncretsym
;
1205 storepos
: tfileposinfo
;
1208 { do we have an assembler block without the po_assembler?
1209 we should allow this for Delphi compatibility (PFV) }
1210 if (token
=_ASM
) and (m_delphi
in aktmodeswitches
) then
1212 include(aktprocsym
^.definition
^.procoptions
,po_assembler
);
1213 block
:=assembler_block
;
1216 if procinfo
^.returntype
.def
<>pdef(voiddef
) then
1218 { if the current is a function aktprocsym is non nil }
1219 { and there is a local symtable set }
1221 tokenpos
:=aktprocsym
^.fileinfo
;
1222 funcretsym
:=new(pfuncretsym
,init(aktprocsym
^.name
,procinfo
));
1223 { insert in local symtable }
1224 symtablestack
^.insert(funcretsym
);
1226 if ret_in_acc(procinfo
^.returntype
.def
) or (procinfo
^.returntype
.def
^.deftype
=floatdef
) then
1227 procinfo
^.return_offset
:=-funcretsym
^.address
;
1228 procinfo
^.funcretsym
:=funcretsym
;
1229 { insert result also if support is on }
1230 if (m_result
in aktmodeswitches
) then
1232 procinfo
^.resultfuncretsym
:=new(pfuncretsym
,init('RESULT',procinfo
));
1233 symtablestack
^.insert(procinfo
^.resultfuncretsym
);
1236 read_declarations(islibrary
);
1238 { temporary space is set, while the BEGIN of the procedure }
1239 if (symtablestack
^.symtabletype
=localsymtable
) then
1240 procinfo
^.firsttemp_offset
:= -symtablestack
^.datasize
1242 procinfo
^.firsttemp_offset
:= 0;
1244 { space for the return value }
1245 { !!!!! this means that we can not set the return value
1246 in a subfunction !!!!! }
1247 { because we don't know yet where the address is }
1248 if procinfo
^.returntype
.def
<>pdef(voiddef
) then
1250 if ret_in_acc(procinfo
^.returntype
.def
) or (procinfo
^.returntype
.def
^.deftype
=floatdef
) then
1251 { if (procinfo^.retdef^.deftype=orddef) or
1252 (procinfo^.retdef^.deftype=pointerdef) or
1253 (procinfo^.retdef^.deftype=enumdef) or
1254 (procinfo^.retdef^.deftype=procvardef) or
1255 (procinfo^.retdef^.deftype=floatdef) or
1257 (procinfo^.retdef^.deftype=setdef) and
1258 (psetdef(procinfo^.retdef)^.settype=smallset)
1261 { the space has been set in the local symtable }
1262 procinfo
^.return_offset
:=-funcretsym
^.address
;
1263 if ((procinfo
^.flags
and pi_operator
)<>0) and
1264 assigned(opsym
) then
1265 {opsym^.address:=procinfo^.para_offset; is wrong PM }
1266 opsym
^.address
:=-procinfo
^.return_offset
;
1267 { eax is modified by a function }
1270 usedinproc
:=usedinproc
or ($80 shr byte(R_EAX
));
1272 if is_64bitint(procinfo
^.returntype
.def
) then
1273 usedinproc
:=usedinproc
or ($80 shr byte(R_EDX
))
1276 usedinproc
:=usedinproc
or ($800 shr word(R_D0
));
1278 if is_64bitint(procinfo
^.retdef
) then
1279 usedinproc
:=usedinproc
or ($800 shr byte(R_D1
))
1285 {Unit initialization?.}
1286 if (lexlevel
=unit_init_level
) and (current_module
^.is_unit
)
1289 if (token
=_END
) then
1292 { We need at least a node, else the entry/exit code is not
1293 generated and thus no PASCALMAIN symbol which we need (PFV) }
1295 block
:=genzeronode(nothingn
)
1301 if token
=_INITIALIZATION
then
1303 current_module
^.flags
:=current_module
^.flags
or uf_init
;
1304 block
:=statement_block(_INITIALIZATION
);
1306 else if (token
=_FINALIZATION
) then
1308 if (current_module
^.flags
and uf_finalize
)<>0 then
1309 block
:=statement_block(_FINALIZATION
)
1312 { can we allow no INITIALIZATION for DLL ??
1313 I think it should work PM }
1320 current_module
^.flags
:=current_module
^.flags
or uf_init
;
1321 block
:=statement_block(_BEGIN
);
1326 block
:=statement_block(_BEGIN
);
1329 function assembler_block
: ptree
;
1332 read_declarations(false);
1333 { temporary space is set, while the BEGIN of the procedure }
1334 if symtablestack
^.symtabletype
=localsymtable
then
1335 procinfo
^.firsttemp_offset
:= -symtablestack
^.datasize
1337 procinfo
^.firsttemp_offset
:= 0;
1339 { assembler code does not allocate }
1340 { space for the return value }
1341 if procinfo
^.returntype
.def
<>pdef(voiddef
) then
1343 if ret_in_acc(procinfo
^.returntype
.def
) then
1345 { in assembler code the result should be directly in %eax
1346 procinfo^.retoffset:=procinfo^.firsttemp-procinfo^.retdef^.size;
1347 procinfo^.firsttemp:=procinfo^.retoffset; }
1351 usedinproc
:=usedinproc
or ($80 shr byte(R_EAX
))
1354 usedinproc
:=usedinproc
or ($800 shr word(R_D0
))
1359 else if not is_fpu(procinfo^.retdef) then
1360 should we allow assembler functions of big elements ?
1362 Message(parser_e_asm_incomp_with_function_return);
1365 { set the framepointer to esp for assembler functions }
1366 { but only if the are no local variables }
1367 { added no parameter also (PM) }
1368 { disable for methods, because self pointer is expected }
1369 { at -8(%ebp) (JM) }
1370 { why if se use %esp then self is still at the correct address PM }
1371 if {not(assigned(procinfo^._class)) and}
1372 (po_assembler
in aktprocsym
^.definition
^.procoptions
) and
1373 (aktprocsym
^.definition
^.localst
^.datasize
=0) and
1374 (aktprocsym
^.definition
^.parast
^.datasize
=0) and
1375 not(ret_in_param(aktprocsym
^.definition
^.rettype
.def
)) then
1377 procinfo
^.framepointer
:=stack_pointer
;
1378 { set the right value for parameters }
1379 dec(aktprocsym
^.definition
^.parast
^.address_fixup
,target_os
.size_of_pointer
);
1380 dec(procinfo
^.para_offset
,target_os
.size_of_pointer
);
1382 { force the asm statement }
1385 procinfo^.Flags := procinfo^.Flags Or pi_is_assembler;
1386 assembler_block:=_asm_statement;
1387 { becuase the END is already read we need to get the
1388 last_endtoken_filepos here (PFV) }
1389 last_endtoken_filepos:=tokenpos;
1395 Revision 1.1 2002/02/19 08:23:34 sasu
1398 Revision 1.1.2.4 2000/11/27 16:05:06 jonas
1399 * fix for web bug 1251 (example 1)
1401 Revision 1.1.2.3 2000/11/22 22:42:42 peter
1402 * fixed crash with exception without sysutils
1404 Revision 1.1.2.2 2000/09/26 08:49:03 pierre
1405 * avoid memory leak with raisen
1407 Revision 1.1.2.1 2000/08/11 15:15:43 florian
1408 * fixed bug 1096 (problem with exit in $X- mode)
1410 Revision 1.1 2000/07/13 06:29:54 michael
1413 Revision 1.131 2000/06/30 22:15:39 peter
1414 * fixed internalerror 2002 when case expr is not correct, by creating
1415 a temp correct case expression
1417 Revision 1.130 2000/05/04 12:59:10 pierre
1418 * bug found by Kovacs Attila Zoltan corrected
1420 Revision 1.129 2000/04/29 12:50:14 peter
1421 * support asm block without assembler directive for -Sd
1423 Revision 1.128 2000/04/24 11:11:50 peter
1424 * backtraces for exceptions are now only generated from the place of the
1426 * frame is also pushed for exceptions
1427 * raise statement enhanced with [,<frame>]
1429 Revision 1.127 2000/03/19 14:17:05 florian
1430 * crash when using exception classes without sysutils unit fixed
1432 Revision 1.126 2000/03/19 11:16:44 peter
1433 * check for unknown id in on exception
1435 Revision 1.125 2000/03/16 15:12:06 pierre
1436 assembler method code does not need ebp framepointer
1438 Revision 1.124 2000/03/14 16:37:25 pierre
1439 * destructor can have args in TP mode only (bug825 and 839)
1441 Revision 1.123 2000/02/29 23:59:47 pierre
1444 Revision 1.122 2000/02/09 13:22:59 peter
1447 Revision 1.121 2000/01/23 16:33:49 peter
1448 * fixed destructor parsing with preprocessor things
1449 * support dipsoe(p,done())
1450 * fixed constructor message with dispose(p,<nonexist>)
1452 Revision 1.120 2000/01/16 22:17:12 peter
1453 * renamed call_offset to para_offset
1455 Revision 1.119 2000/01/12 10:30:50 peter
1456 * fixed library with only end.
1458 Revision 1.118 2000/01/07 01:14:31 peter
1459 * updated copyright to 2000
1461 Revision 1.117 1999/12/22 01:01:52 peter
1462 - removed freelabel()
1463 * added undefined label detection in internal assembler, this prevents
1464 a lot of ld crashes and wrong .o files
1465 * .o files aren't written anymore if errors have occured
1466 * inlining of assembler labels is now correct
1468 Revision 1.116 1999/12/14 09:58:42 florian
1469 + compiler checks now if a goto leaves an exception block
1471 Revision 1.115 1999/12/01 22:43:17 peter
1472 * fixed sigsegv with casedef=nil
1474 Revision 1.114 1999/12/01 12:42:32 peter
1476 * removed some notes about unused vars
1478 Revision 1.113 1999/11/30 10:40:45 peter
1481 Revision 1.112 1999/11/20 01:19:10 pierre
1482 * DLL index used for win32 target with DEF file
1483 + DLL initialization/finalization support
1485 Revision 1.111 1999/11/18 15:34:48 pierre
1486 * Notes/Hints for local syms changed to
1487 Set_varstate function
1489 Revision 1.110 1999/11/17 17:05:02 pierre
1490 * Notes/hints changes
1492 Revision 1.109 1999/11/15 22:00:48 peter
1493 * labels used but not defined give error instead of warning, the warning
1494 is now only with declared but not defined and not used.
1496 Revision 1.108 1999/11/10 00:24:02 pierre
1497 * more browser details
1499 Revision 1.107 1999/11/09 13:02:46 peter
1500 * fixed 'raise end;'
1502 Revision 1.106 1999/11/06 14:34:23 peter
1503 * truncated log to 20 revs
1505 Revision 1.105 1999/10/22 10:39:35 peter
1506 * split type reading from pdecl to ptype unit
1507 * parameter_dec routine is now used for procedure and procvars
1509 Revision 1.104 1999/10/14 14:57:54 florian
1510 - removed the hcodegen use in the new cg, use cgbase instead
1512 Revision 1.103 1999/09/27 23:44:56 peter
1513 * procinfo is now a pointer
1514 * support for result setting in sub procedure
1516 Revision 1.102 1999/09/16 23:05:54 florian
1517 * m68k compiler is again compilable (only gas writer, no assembler reader)