|
@@ -42,10 +42,7 @@ interface
|
|
|
end;
|
|
|
|
|
|
tcgfornode = class(tfornode)
|
|
|
- usedregvars: tusedregvars;
|
|
|
-
|
|
|
procedure pass_generate_code;override;
|
|
|
- procedure sync_regvars(checkusedregvars: boolean);
|
|
|
end;
|
|
|
|
|
|
tcgexitnode = class(texitnode)
|
|
@@ -186,15 +183,15 @@ implementation
|
|
|
|
|
|
hlcg.a_label(current_asmdata.CurrAsmList,lcont);
|
|
|
if lnf_checknegate in loopflags then
|
|
|
- begin
|
|
|
+ begin
|
|
|
truelabel:=lbreak;
|
|
|
falselabel:=lloop;
|
|
|
- end
|
|
|
+ end
|
|
|
else
|
|
|
- begin
|
|
|
+ begin
|
|
|
truelabel:=lloop;
|
|
|
falselabel:=lbreak;
|
|
|
- end;
|
|
|
+ end;
|
|
|
secondpass(left);
|
|
|
|
|
|
hlcg.maketojumpboollabels(current_asmdata.CurrAsmList,left,truelabel,falselabel);
|
|
@@ -379,435 +376,10 @@ implementation
|
|
|
SecondFor
|
|
|
*****************************************************************************}
|
|
|
|
|
|
- procedure tcgfornode.sync_regvars(checkusedregvars: boolean);
|
|
|
- begin
|
|
|
- if (cs_opt_regvar in current_settings.optimizerswitches) and
|
|
|
- not(pi_has_label in current_procinfo.flags) then
|
|
|
- begin
|
|
|
- if checkusedregvars then
|
|
|
- begin
|
|
|
- usedregvars.intregvars.init;
|
|
|
- usedregvars.addrregvars.init;
|
|
|
- usedregvars.fpuregvars.init;
|
|
|
- usedregvars.mmregvars.init;
|
|
|
-
|
|
|
- { We have to synchronise the loop variable and loop body. }
|
|
|
- { The loop end is not necessary, unless it's a register }
|
|
|
- { variable. The start value also doesn't matter. }
|
|
|
-
|
|
|
- { loop var }
|
|
|
- get_used_regvars(left,usedregvars);
|
|
|
- { loop body }
|
|
|
- get_used_regvars(t2,usedregvars);
|
|
|
- { end value can't be a regvar, but may be a temp in register }
|
|
|
- get_used_regvars(t1,usedregvars);
|
|
|
-
|
|
|
- gen_sync_regvars(current_asmdata.CurrAsmList,usedregvars);
|
|
|
- end
|
|
|
- else
|
|
|
- begin
|
|
|
- gen_sync_regvars(current_asmdata.CurrAsmList,usedregvars);
|
|
|
- usedregvars.intregvars.done;
|
|
|
- usedregvars.addrregvars.done;
|
|
|
- usedregvars.fpuregvars.done;
|
|
|
- usedregvars.mmregvars.done;
|
|
|
- end;
|
|
|
- end;
|
|
|
- end;
|
|
|
-
|
|
|
-
|
|
|
procedure tcgfornode.pass_generate_code;
|
|
|
- var
|
|
|
- l3,oldclabel,oldblabel : tasmlabel;
|
|
|
- temptovalue : boolean;
|
|
|
- hop : topcg;
|
|
|
- hcond : topcmp;
|
|
|
- opsize : tcgsize;
|
|
|
- count_var_is_signed,do_loopvar_at_end : boolean;
|
|
|
- cmp_const:Tconstexprint;
|
|
|
- oldflowcontrol : tflowcontrol;
|
|
|
- oldexecutionweight : longint;
|
|
|
begin
|
|
|
- location_reset(location,LOC_VOID,OS_NO);
|
|
|
-
|
|
|
- oldclabel:=current_procinfo.CurrContinueLabel;
|
|
|
- oldblabel:=current_procinfo.CurrBreakLabel;
|
|
|
- current_asmdata.getjumplabel(current_procinfo.CurrContinueLabel);
|
|
|
- current_asmdata.getjumplabel(current_procinfo.CurrBreakLabel);
|
|
|
- current_asmdata.getjumplabel(l3);
|
|
|
-
|
|
|
- { only calculate reference }
|
|
|
- opsize := def_cgsize(left.resultdef);
|
|
|
- count_var_is_signed:=is_signed(left.resultdef);
|
|
|
-
|
|
|
- { first set the to value
|
|
|
- because the count var can be in the expression ! }
|
|
|
- do_loopvar_at_end:=(lnf_dont_mind_loopvar_on_exit in loopflags)
|
|
|
- { if the loop is unrolled and there is a jump into the loop,
|
|
|
- then we can't do the trick with incrementing the loop var only at the
|
|
|
- end
|
|
|
- }
|
|
|
- and not(assigned(entrylabel));
|
|
|
-
|
|
|
- secondpass(t1);
|
|
|
- if t1.location.loc in [LOC_FLAGS,LOC_JUMP] then
|
|
|
- hlcg.location_force_reg(current_asmdata.CurrAsmList,t1.location,t1.resultdef,t1.resultdef,false);
|
|
|
- { calculate pointer value and check if changeable and if so }
|
|
|
- { load into temporary variable }
|
|
|
- if t1.nodetype<>ordconstn then
|
|
|
- begin
|
|
|
- do_loopvar_at_end:=false;
|
|
|
- temptovalue:=true;
|
|
|
- end
|
|
|
- else
|
|
|
- temptovalue:=false;
|
|
|
-
|
|
|
- { load loopvar, prefer loopvar being a register variable }
|
|
|
- oldexecutionweight:=cg.executionweight;
|
|
|
- inc(cg.executionweight,8);
|
|
|
- secondpass(left);
|
|
|
- cg.executionweight:=oldexecutionweight;
|
|
|
-
|
|
|
- { load from value }
|
|
|
- secondpass(right);
|
|
|
- if right.location.loc in [LOC_FLAGS,LOC_JUMP] then
|
|
|
- hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,right.resultdef,false);
|
|
|
-
|
|
|
- hlcg.maybe_change_load_node_reg(current_asmdata.CurrAsmList,left,false);
|
|
|
- oldflowcontrol:=flowcontrol;
|
|
|
- include(flowcontrol,fc_inflowcontrol);
|
|
|
- exclude(flowcontrol,fc_unwind_loop);
|
|
|
- { produce start assignment }
|
|
|
- case left.location.loc of
|
|
|
- LOC_REFERENCE,
|
|
|
- LOC_CREFERENCE :
|
|
|
- hlcg.a_load_loc_ref(current_asmdata.CurrAsmList,right.resultdef,left.resultdef,right.location,left.location.reference);
|
|
|
- LOC_REGISTER,
|
|
|
- LOC_CREGISTER:
|
|
|
- hlcg.a_load_loc_reg(current_asmdata.CurrAsmList,right.resultdef,left.resultdef,right.location,left.location.register);
|
|
|
- LOC_SUBSETREG,
|
|
|
- LOC_CSUBSETREG :
|
|
|
- hlcg.a_load_loc_subsetreg(current_asmdata.CurrAsmList,right.resultdef,left.resultdef,right.location,left.location.sreg);
|
|
|
- else
|
|
|
- internalerror(200501311);
|
|
|
- end;
|
|
|
-
|
|
|
- if lnf_backward in loopflags then
|
|
|
- if count_var_is_signed then
|
|
|
- hcond:=OC_LT
|
|
|
- else
|
|
|
- hcond:=OC_B
|
|
|
- else
|
|
|
- if count_var_is_signed then
|
|
|
- hcond:=OC_GT
|
|
|
- else
|
|
|
- hcond:=OC_A;
|
|
|
-
|
|
|
- sync_regvars(true);
|
|
|
-{$ifdef OLDREGVARS}
|
|
|
- load_all_regvars(current_asmdata.CurrAsmList);
|
|
|
-{$endif OLDREGVARS}
|
|
|
-
|
|
|
- if temptovalue then
|
|
|
- begin
|
|
|
- case t1.location.loc of
|
|
|
- LOC_REGISTER,LOC_CREGISTER:
|
|
|
- hlcg.a_cmp_reg_loc_label(current_asmdata.CurrAsmList,left.resultdef,hcond,
|
|
|
- t1.location.register,left.location,current_procinfo.CurrBreakLabel);
|
|
|
- LOC_REFERENCE,LOC_CREFERENCE:
|
|
|
- hlcg.a_cmp_ref_loc_label(current_asmdata.CurrAsmList,left.resultdef,hcond,
|
|
|
- t1.location.reference,left.location,current_procinfo.CurrBreakLabel);
|
|
|
- else
|
|
|
- InternalError(2013051601);
|
|
|
- end;
|
|
|
- end
|
|
|
- else
|
|
|
- begin
|
|
|
- if lnf_testatbegin in loopflags then
|
|
|
- begin
|
|
|
- hlcg.a_cmp_const_loc_label(current_asmdata.CurrAsmList,left.resultdef,hcond,
|
|
|
- tordconstnode(t1).value.svalue,
|
|
|
- left.location,current_procinfo.CurrBreakLabel);
|
|
|
- end;
|
|
|
- end;
|
|
|
-
|
|
|
- {If the loopvar doesn't mind on exit, we avoid this ugly
|
|
|
- dec instruction and do the loopvar inc/dec after the loop
|
|
|
- body.}
|
|
|
- if not do_loopvar_at_end then
|
|
|
- begin
|
|
|
- if lnf_backward in loopflags then
|
|
|
- hop:=OP_ADD
|
|
|
- else
|
|
|
- hop:=OP_SUB;
|
|
|
- hlcg.a_op_const_loc(current_asmdata.CurrAsmList,hop,left.resultdef,1,left.location);
|
|
|
- end;
|
|
|
-
|
|
|
- if assigned(entrylabel) then
|
|
|
- hlcg.a_jmp_always(current_asmdata.CurrAsmList,tcglabelnode(entrylabel).getasmlabel);
|
|
|
-
|
|
|
- { align loop target }
|
|
|
- if not(cs_opt_size in current_settings.optimizerswitches) then
|
|
|
- current_asmdata.CurrAsmList.concat(Tai_align.Create(current_settings.alignment.loopalign));
|
|
|
- hlcg.a_label(current_asmdata.CurrAsmList,l3);
|
|
|
-
|
|
|
- {If the loopvar doesn't mind on exit, we avoid the loopvar inc/dec
|
|
|
- after the loop body instead of here.}
|
|
|
- if not do_loopvar_at_end then
|
|
|
- begin
|
|
|
- { according to count direction DEC or INC... }
|
|
|
- if lnf_backward in loopflags then
|
|
|
- hop:=OP_SUB
|
|
|
- else
|
|
|
- hop:=OP_ADD;
|
|
|
- hlcg.a_op_const_loc(current_asmdata.CurrAsmList,hop,left.resultdef,1,left.location);
|
|
|
- end;
|
|
|
-
|
|
|
- if assigned(t2) then
|
|
|
- begin
|
|
|
- { Calc register weight }
|
|
|
- oldexecutionweight:=cg.executionweight;
|
|
|
- cg.executionweight:=cg.executionweight*8;
|
|
|
- secondpass(t2);
|
|
|
- cg.executionweight:=oldexecutionweight;
|
|
|
-{$ifdef OLDREGVARS}
|
|
|
- load_all_regvars(current_asmdata.CurrAsmList);
|
|
|
-{$endif OLDREGVARS}
|
|
|
- end;
|
|
|
-
|
|
|
- {If the loopvar doesn't mind on exit, we do the loopvar inc/dec
|
|
|
- after the loop body instead of here.}
|
|
|
- if do_loopvar_at_end then
|
|
|
- begin
|
|
|
- { according to count direction DEC or INC... }
|
|
|
- if lnf_backward in loopflags then
|
|
|
- hop:=OP_SUB
|
|
|
- else
|
|
|
- hop:=OP_ADD;
|
|
|
- hlcg.a_op_const_loc(current_asmdata.CurrAsmList,hop,left.resultdef,1,left.location);
|
|
|
- end;
|
|
|
-
|
|
|
- hlcg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrContinueLabel);
|
|
|
-
|
|
|
- if do_loopvar_at_end then
|
|
|
- if lnf_backward in loopflags then
|
|
|
- if count_var_is_signed then
|
|
|
- hcond:=OC_GTE
|
|
|
- else
|
|
|
- hcond:=OC_AE
|
|
|
- else
|
|
|
- if count_var_is_signed then
|
|
|
- hcond:=OC_LTE
|
|
|
- else
|
|
|
- hcond:=OC_BE
|
|
|
- else
|
|
|
- if lnf_backward in loopflags then
|
|
|
- if count_var_is_signed then
|
|
|
- hcond:=OC_GT
|
|
|
- else
|
|
|
- hcond:=OC_A
|
|
|
- else
|
|
|
- if count_var_is_signed then
|
|
|
- hcond:=OC_LT
|
|
|
- else
|
|
|
- hcond:=OC_B;
|
|
|
-{$ifdef OLDREGVARS}
|
|
|
- load_all_regvars(current_asmdata.CurrAsmList);
|
|
|
-{$endif OLDREGVARS}
|
|
|
-
|
|
|
- { produce comparison and the corresponding }
|
|
|
- { jump }
|
|
|
- if temptovalue then
|
|
|
- begin
|
|
|
- case t1.location.loc of
|
|
|
- LOC_REGISTER,LOC_CREGISTER:
|
|
|
- hlcg.a_cmp_reg_loc_label(current_asmdata.CurrAsmList,left.resultdef,hcond,t1.location.register,
|
|
|
- left.location,l3);
|
|
|
- LOC_REFERENCE,LOC_CREFERENCE:
|
|
|
- hlcg.a_cmp_ref_loc_label(current_asmdata.CurrAsmList,left.resultdef,hcond,t1.location.reference,
|
|
|
- left.location,l3);
|
|
|
- else
|
|
|
- InternalError(2013051602);
|
|
|
- end;
|
|
|
- end
|
|
|
- else
|
|
|
- begin
|
|
|
- cmp_const:=Tordconstnode(t1).value;
|
|
|
- if do_loopvar_at_end then
|
|
|
- begin
|
|
|
- {Watch out for wrap around 255 -> 0.}
|
|
|
- {Ugly: This code is way to long... Use tables?}
|
|
|
- case opsize of
|
|
|
- OS_8:
|
|
|
- begin
|
|
|
- if lnf_backward in loopflags then
|
|
|
- begin
|
|
|
- if byte(cmp_const.svalue)=low(byte) then
|
|
|
- begin
|
|
|
- hcond:=OC_NE;
|
|
|
- cmp_const:=high(byte);
|
|
|
- end
|
|
|
- end
|
|
|
- else
|
|
|
- begin
|
|
|
- if byte(cmp_const.svalue)=high(byte) then
|
|
|
- begin
|
|
|
- hcond:=OC_NE;
|
|
|
- cmp_const:=low(byte);
|
|
|
- end
|
|
|
- end
|
|
|
- end;
|
|
|
- OS_16:
|
|
|
- begin
|
|
|
- if lnf_backward in loopflags then
|
|
|
- begin
|
|
|
- if word(cmp_const.svalue)=high(word) then
|
|
|
- begin
|
|
|
- hcond:=OC_NE;
|
|
|
- cmp_const:=low(word);
|
|
|
- end
|
|
|
- end
|
|
|
- else
|
|
|
- begin
|
|
|
- if word(cmp_const.svalue)=low(word) then
|
|
|
- begin
|
|
|
- hcond:=OC_NE;
|
|
|
- cmp_const:=high(word);
|
|
|
- end
|
|
|
- end
|
|
|
- end;
|
|
|
- OS_32:
|
|
|
- begin
|
|
|
- if lnf_backward in loopflags then
|
|
|
- begin
|
|
|
- if cardinal(cmp_const.svalue)=high(cardinal) then
|
|
|
- begin
|
|
|
- hcond:=OC_NE;
|
|
|
- cmp_const:=low(cardinal);
|
|
|
- end
|
|
|
- end
|
|
|
- else
|
|
|
- begin
|
|
|
- if cardinal(cmp_const.svalue)=low(cardinal) then
|
|
|
- begin
|
|
|
- hcond:=OC_NE;
|
|
|
- cmp_const:=high(cardinal);
|
|
|
- end
|
|
|
- end
|
|
|
- end;
|
|
|
- OS_64:
|
|
|
- begin
|
|
|
- if lnf_backward in loopflags then
|
|
|
- begin
|
|
|
- if qword(cmp_const.uvalue)=high(qword) then
|
|
|
- begin
|
|
|
- hcond:=OC_NE;
|
|
|
- cmp_const:=low(qword);
|
|
|
- end
|
|
|
- end
|
|
|
- else
|
|
|
- begin
|
|
|
- if qword(cmp_const.uvalue)=low(qword) then
|
|
|
- begin
|
|
|
- hcond:=OC_NE;
|
|
|
- cmp_const:=high(qword);
|
|
|
- end
|
|
|
- end
|
|
|
- end;
|
|
|
- OS_S8:
|
|
|
- begin
|
|
|
- if lnf_backward in loopflags then
|
|
|
- begin
|
|
|
- if shortint(cmp_const.svalue)=low(shortint) then
|
|
|
- begin
|
|
|
- hcond:=OC_NE;
|
|
|
- cmp_const:=high(shortint);
|
|
|
- end
|
|
|
- end
|
|
|
- else
|
|
|
- begin
|
|
|
- if shortint(cmp_const.svalue)=high(shortint) then
|
|
|
- begin
|
|
|
- hcond:=OC_NE;
|
|
|
- cmp_const:=int64(low(shortint));
|
|
|
- end
|
|
|
- end
|
|
|
- end;
|
|
|
- OS_S16:
|
|
|
- begin
|
|
|
- if lnf_backward in loopflags then
|
|
|
- begin
|
|
|
- if integer(cmp_const.svalue)=high(smallint) then
|
|
|
- begin
|
|
|
- hcond:=OC_NE;
|
|
|
- cmp_const:=int64(low(smallint));
|
|
|
- end
|
|
|
- end
|
|
|
- else
|
|
|
- begin
|
|
|
- if integer(cmp_const.svalue)=low(smallint) then
|
|
|
- begin
|
|
|
- hcond:=OC_NE;
|
|
|
- cmp_const:=int64(high(smallint));
|
|
|
- end
|
|
|
- end
|
|
|
- end;
|
|
|
- OS_S32:
|
|
|
- begin
|
|
|
- if lnf_backward in loopflags then
|
|
|
- begin
|
|
|
- if longint(cmp_const.svalue)=high(longint) then
|
|
|
- begin
|
|
|
- hcond:=OC_NE;
|
|
|
- cmp_const:=int64(low(longint));
|
|
|
- end
|
|
|
- end
|
|
|
- else
|
|
|
- begin
|
|
|
- if longint(cmp_const.svalue)=low(longint) then
|
|
|
- begin
|
|
|
- hcond:=OC_NE;
|
|
|
- cmp_const:=int64(high(longint));
|
|
|
- end
|
|
|
- end
|
|
|
- end;
|
|
|
- OS_S64:
|
|
|
- begin
|
|
|
- if lnf_backward in loopflags then
|
|
|
- begin
|
|
|
- if int64(cmp_const.svalue)=high(int64) then
|
|
|
- begin
|
|
|
- hcond:=OC_NE;
|
|
|
- cmp_const:=low(int64);
|
|
|
- end
|
|
|
- end
|
|
|
- else
|
|
|
- begin
|
|
|
- if int64(cmp_const.svalue)=low(int64) then
|
|
|
- begin
|
|
|
- hcond:=OC_NE;
|
|
|
- cmp_const:=high(int64);
|
|
|
- end
|
|
|
- end
|
|
|
- end;
|
|
|
- else
|
|
|
- internalerror(200201021);
|
|
|
- end;
|
|
|
- end;
|
|
|
-
|
|
|
- hlcg.a_cmp_const_loc_label(current_asmdata.CurrAsmList,left.resultdef,hcond,
|
|
|
- tcgint(cmp_const.svalue),left.location,l3);
|
|
|
- end;
|
|
|
-
|
|
|
- { this is the break label: }
|
|
|
- hlcg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrBreakLabel);
|
|
|
-
|
|
|
- sync_regvars(false);
|
|
|
-
|
|
|
- current_procinfo.CurrContinueLabel:=oldclabel;
|
|
|
- current_procinfo.CurrBreakLabel:=oldblabel;
|
|
|
- { a break/continue in a while/repeat block can't be seen outside }
|
|
|
- flowcontrol:=oldflowcontrol+(flowcontrol-[fc_break,fc_continue,fc_inflowcontrol]);
|
|
|
+ { for nodes are converted in pass_1 in a while loop }
|
|
|
+ internalerror(2015082501);
|
|
|
end;
|
|
|
|
|
|
|