+ inline high(<dyn. array>), resolves #28536

git-svn-id: trunk@43808 -
This commit is contained in:
florian 2019-12-28 21:38:38 +00:00
parent 3418f0e977
commit f7a052f884
3 changed files with 94 additions and 17 deletions

View File

@ -66,6 +66,7 @@ interface
procedure second_seg; virtual; abstract;
procedure second_fma; virtual;
procedure second_frac_real; virtual;
procedure second_high; virtual;
protected
function second_incdec_tempregdef: tdef;virtual;
end;
@ -226,6 +227,8 @@ implementation
in_neg_assign_x,
in_not_assign_x:
second_NegNot_assign;
in_high_x:
second_high;
else
pass_generate_code_cpu;
end;
@ -303,6 +306,42 @@ implementation
end;
end;
{*****************************************************************************
HIGH(<dyn. array>) GENERIC HANDLING
*****************************************************************************}
procedure tcginlinenode.second_high;
var
loadlab, nillab, donelab: tasmlabel;
hregister : tregister;
href : treference;
begin
secondpass(left);
if not(is_dynamic_array(left.resultdef)) then
Internalerror(2019122801);
{ length in dynamic arrays is at offset -sizeof(pint) }
hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,false);
current_asmdata.getjumplabel(loadlab);
current_asmdata.getjumplabel(nillab);
current_asmdata.getjumplabel(donelab);
hlcg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,left.resultdef,OC_EQ,0,left.location.register,nillab);
{ volatility of the dyn. array refers to the volatility of the
string pointer, not of the string data }
hlcg.reference_reset_base(href,left.resultdef,left.location.register,-ossinttype.size,ctempposinvalid,ossinttype.alignment,[]);
{ if the string pointer is nil, the length is 0 -> reuse the register
that originally held the string pointer for the length, so that we
can keep the original nil/0 as length in that case }
hregister:=cg.makeregsize(current_asmdata.CurrAsmList,left.location.register,def_cgsize(resultdef));
hlcg.a_load_ref_reg(current_asmdata.CurrAsmList,ossinttype,resultdef,href,hregister);
hlcg.a_jmp_always(current_asmdata.CurrAsmList,donelab);
cg.a_label(current_asmdata.CurrAsmList,nillab);
hlcg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SUB,resultdef,1,hregister);
cg.a_label(current_asmdata.CurrAsmList,donelab);
location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
location.register:=hregister;
end;
{*****************************************************************************
PRED/SUCC GENERIC HANDLING

View File

@ -85,6 +85,7 @@ interface
by the JVM backend to create new dynamic arrays. }
function first_new: tnode; virtual;
function first_length: tnode; virtual;
function first_high: tnode; virtual;
function first_box: tnode; virtual; abstract;
function first_unbox: tnode; virtual; abstract;
function first_assigned: tnode; virtual;
@ -3484,21 +3485,10 @@ implementation
result:=load_high_value_node(tparavarsym(tloadnode(left).symtableentry));
end
else
if is_dynamic_array(left.resultdef) then
begin
set_varstate(left,vs_read,[vsf_must_be_valid]);
{ can't use inserttypeconv because we need }
{ an explicit type conversion (JM) }
hp := ccallparanode.create(ctypeconvnode.create_internal(left,voidpointertype),nil);
result := ccallnode.createintern('fpc_dynarray_high',hp);
{ make sure the left node doesn't get disposed, since it's }
{ reused in the new node (JM) }
left:=nil;
end
else
begin
set_varstate(left,vs_read,[]);
end;
begin
set_varstate(left,vs_read,[]);
resultdef:=sizesinttype;
end;
end;
end;
stringdef:
@ -4047,9 +4037,12 @@ implementation
result:=first_assert;
end;
in_low_x,
in_high_x:
in_low_x:
internalerror(200104047);
in_high_x:
begin
result:=first_high;
end;
in_slice_x:
internalerror(2005101501);
@ -4705,6 +4698,15 @@ implementation
end;
function tinlinenode.first_high: tnode;
begin
result:=nil;
if not(is_dynamic_array(left.resultdef)) then
Internalerror(2019122802);
expectloc:=LOC_REGISTER;
end;
function tinlinenode.first_assigned: tnode;
begin
{ Comparison must not call procvars, indicate that with nf_load_procvar flag }

View File

@ -78,6 +78,7 @@ interface
procedure second_fma;override;
procedure second_frac_real;override;
procedure second_int_real;override;
procedure second_high;override;
private
procedure load_fpu_location(lnode: tnode);
end;
@ -1271,4 +1272,39 @@ implementation
internalerror(2017052107);
end;
procedure tx86inlinenode.second_high;
var
donelab: tasmlabel;
hregister : tregister;
href : treference;
begin
secondpass(left);
if not(is_dynamic_array(left.resultdef)) then
Internalerror(2019122801);
{ length in dynamic arrays is at offset -sizeof(pint) }
hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,false);
current_asmdata.getjumplabel(donelab);
{ by subtracting 1 here, we get the -1 into the register we need if the dyn. array is nil and the carry
flag is set in this case, so we can jump depending on it
when loading the actual high value, we have to take care later of the decreased value }
hlcg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SUB,left.resultdef,1,left.location.register);
{ volatility of the dyn. array refers to the volatility of the
string pointer, not of the string data }
cg.a_jmp_flags(current_asmdata.CurrAsmList,F_C,donelab);
hlcg.reference_reset_base(href,left.resultdef,left.location.register,-ossinttype.size+1,ctempposinvalid,ossinttype.alignment,[]);
{ if the string pointer is nil, the length is 0 -> reuse the register
that originally held the string pointer for the length, so that we
can keep the original nil/0 as length in that case }
hregister:=cg.makeregsize(current_asmdata.CurrAsmList,left.location.register,def_cgsize(resultdef));
hlcg.a_load_ref_reg(current_asmdata.CurrAsmList,ossinttype,resultdef,href,hregister);
cg.a_label(current_asmdata.CurrAsmList,donelab);
location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
location.register:=hregister;
end;
end.