mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-16 13:59:28 +02:00
* sign extend all byte/ansichar/word parameters before passing them
to and returning them from sub routines, in order to follow the JVM specs to the letter (not checked by the JVM bytecode verifiers, but checked by the Android DEX verifier) * -> also zero-extend them again at the caller side after returning from such a function git-svn-id: branches/jvmbackend@18919 -
This commit is contained in:
parent
f21b34c954
commit
1a7c024ad3
@ -121,6 +121,7 @@ implementation
|
||||
paraloc : pcgparalocation;
|
||||
retcgsize : tcgsize;
|
||||
begin
|
||||
def:=get_para_push_size(def);
|
||||
result.init;
|
||||
result.alignment:=get_para_align(p.proccalloption);
|
||||
result.def:=def;
|
||||
@ -204,6 +205,7 @@ implementation
|
||||
paracgsize:=OS_ADDR;
|
||||
paradef:=hp.vardef;
|
||||
end;
|
||||
paradef:=get_para_push_size(paradef);
|
||||
hp.paraloc[side].reset;
|
||||
hp.paraloc[side].size:=paracgsize;
|
||||
hp.paraloc[side].def:=paradef;
|
||||
|
@ -48,6 +48,8 @@ uses
|
||||
|
||||
function def2regtyp(def: tdef): tregistertype; override;
|
||||
|
||||
procedure a_load_const_cgpara(list : TAsmList;tosize : tdef;a : aint;const cgpara : TCGPara);override;
|
||||
|
||||
procedure a_call_name(list : TAsmList;pd : tprocdef;const s : TSymStr; weak: boolean);override;
|
||||
procedure a_call_name_inherited(list : TAsmList;pd : tprocdef;const s : TSymStr);override;
|
||||
|
||||
@ -151,6 +153,12 @@ uses
|
||||
{ performs sign/zero extension as required }
|
||||
procedure resize_stack_int_val(list: TAsmList;fromsize,tosize: tcgsize; forarraystore: boolean);
|
||||
|
||||
{ 8/16 bit unsigned parameters and return values must be sign-extended on
|
||||
the producer side, because the JVM does not support unsigned variants;
|
||||
then they have to be zero-extended again on the consumer side }
|
||||
procedure maybe_resize_stack_para_val(list: TAsmList; retdef: tdef; callside: boolean);
|
||||
|
||||
|
||||
property maxevalstackheight: longint read fmaxevalstackheight;
|
||||
|
||||
procedure gen_initialize_fields_code(list:TAsmList);
|
||||
@ -271,6 +279,16 @@ implementation
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure thlcgjvm.a_load_const_cgpara(list: TAsmList; tosize: tdef; a: aint; const cgpara: TCGPara);
|
||||
begin
|
||||
tosize:=get_para_push_size(tosize);
|
||||
if tosize=s8inttype then
|
||||
a:=shortint(a)
|
||||
else if tosize=s16inttype then
|
||||
a:=smallint(a);
|
||||
inherited a_load_const_cgpara(list, tosize, a, cgpara);
|
||||
end;
|
||||
|
||||
procedure thlcgjvm.a_call_name(list: TAsmList; pd: tprocdef; const s: TSymStr; weak: boolean);
|
||||
begin
|
||||
a_call_name_intern(list,pd,s,false);
|
||||
@ -702,7 +720,7 @@ implementation
|
||||
st_shortstring:
|
||||
begin
|
||||
inc(parasize);
|
||||
a_load_const_stack(list,u8inttype,tstringdef(elemdef).len,R_INTREGISTER);
|
||||
a_load_const_stack(list,s8inttype,shortint(tstringdef(elemdef).len),R_INTREGISTER);
|
||||
g_call_system_proc(list,'fpc_initialize_array_shortstring');
|
||||
end;
|
||||
st_ansistring:
|
||||
@ -1429,6 +1447,7 @@ implementation
|
||||
procedure thlcgjvm.g_proc_exit(list: TAsmList; parasize: longint; nostackframe: boolean);
|
||||
var
|
||||
retdef: tdef;
|
||||
cgsize: tcgsize;
|
||||
opc: tasmop;
|
||||
begin
|
||||
if current_procinfo.procdef.proctypeoption in [potype_constructor,potype_class_constructor] then
|
||||
@ -1972,6 +1991,31 @@ implementation
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure thlcgjvm.maybe_resize_stack_para_val(list: TAsmList; retdef: tdef; callside: boolean);
|
||||
var
|
||||
cgsize: tcgsize;
|
||||
begin
|
||||
if (retdef.typ=orddef) then
|
||||
begin
|
||||
if (torddef(retdef).ordtype in [u8bit,u16bit,uchar]) and
|
||||
(torddef(retdef).high>=(1 shl (retdef.size*8-1))) then
|
||||
begin
|
||||
cgsize:=OS_NO;
|
||||
if callside then
|
||||
if torddef(retdef).ordtype in [u8bit,uchar] then
|
||||
cgsize:=OS_S8
|
||||
else
|
||||
cgsize:=OS_S16
|
||||
else if torddef(retdef).ordtype in [u8bit,uchar] then
|
||||
cgsize:=OS_8
|
||||
else
|
||||
cgsize:=OS_16;
|
||||
if cgsize<>OS_NO then
|
||||
resize_stack_int_val(list,OS_S32,cgsize,false);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure thlcgjvm.allocate_implicit_struct_with_base_ref(list: TAsmList; vs: tabstractvarsym; ref: treference);
|
||||
var
|
||||
tmpref: treference;
|
||||
|
@ -81,6 +81,8 @@ interface
|
||||
|
||||
function jvmgetcorrespondingclassdef(def: tdef): tdef;
|
||||
|
||||
function get_para_push_size(def: tdef): tdef;
|
||||
|
||||
{ threadvars are wrapped via descendents of java.lang.ThreadLocal }
|
||||
function jvmgetthreadvardef(def: tdef): tdef;
|
||||
|
||||
@ -92,7 +94,7 @@ interface
|
||||
implementation
|
||||
|
||||
uses
|
||||
cutils,cclasses,
|
||||
cutils,cclasses,constexp,
|
||||
verbose,systems,
|
||||
fmodule,
|
||||
symtable,symconst,symsym,symdef,symcreat,
|
||||
@ -745,6 +747,21 @@ implementation
|
||||
end;
|
||||
|
||||
|
||||
function get_para_push_size(def: tdef): tdef;
|
||||
begin
|
||||
result:=def;
|
||||
if def.typ=orddef then
|
||||
case torddef(def).ordtype of
|
||||
u8bit,uchar:
|
||||
if torddef(def).high>127 then
|
||||
result:=s8inttype;
|
||||
u16bit:
|
||||
if torddef(def).high>32767 then
|
||||
result:=s16inttype;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
function jvmgetthreadvardef(def: tdef): tdef;
|
||||
begin
|
||||
if (def.typ=arraydef) and
|
||||
|
@ -404,8 +404,16 @@ implementation
|
||||
if (tabstractprocdef(procdefinition).proctypeoption=potype_constructor) then
|
||||
totalremovesize:=pushedparasize
|
||||
else
|
||||
{ even a byte takes up a full stackslot -> align size to multiple of 4 }
|
||||
totalremovesize:=pushedparasize-(align(realresdef.size,4) shr 2);
|
||||
begin
|
||||
{ zero-extend unsigned 8/16 bit returns (we have to return them
|
||||
sign-extended to keep the Android verifier happy, and even if that
|
||||
one did not exist a plain Java routine could return a
|
||||
sign-extended value) }
|
||||
if cnf_return_value_used in callnodeflags then
|
||||
thlcgjvm(hlcg).maybe_resize_stack_para_val(current_asmdata.CurrAsmList,realresdef,false);
|
||||
{ even a byte takes up a full stackslot -> align size to multiple of 4 }
|
||||
totalremovesize:=pushedparasize-(align(realresdef.size,4) shr 2);
|
||||
end;
|
||||
{ remove parameters from internal evaluation stack counter (in case of
|
||||
e.g. no parameters and a result, it can also increase) }
|
||||
if totalremovesize>0 then
|
||||
|
@ -191,8 +191,9 @@ unit tgcpu;
|
||||
if is_shortstring(def) then
|
||||
begin
|
||||
gettemp(list,java_jlobject.size,java_jlobject.alignment,temptype,ref);
|
||||
{ add the maxlen parameter }
|
||||
thlcgjvm(hlcg).a_load_const_stack(list,u8inttype,tstringdef(def).len,R_INTREGISTER);
|
||||
{ add the maxlen parameter (s8inttype because parameters must
|
||||
be sign extended) }
|
||||
thlcgjvm(hlcg).a_load_const_stack(list,s8inttype,shortint(tstringdef(def).len),R_INTREGISTER);
|
||||
{ call the constructor }
|
||||
sym:=tsym(tobjectdef(java_shortstring).symtable.find('CREATEEMPTY'));
|
||||
if assigned(sym) and
|
||||
|
@ -36,7 +36,7 @@ interface
|
||||
protected
|
||||
tempcgpara : tcgpara;
|
||||
procedure push_addr_para;
|
||||
procedure push_value_para;
|
||||
procedure push_value_para;virtual;
|
||||
procedure push_formal_para;virtual;
|
||||
procedure push_copyout_para;virtual;abstract;
|
||||
public
|
||||
|
Loading…
Reference in New Issue
Block a user