* 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:
Jonas Maebe 2011-08-30 23:34:12 +00:00
parent f21b34c954
commit 1a7c024ad3
6 changed files with 79 additions and 7 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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