+ support for (formal/untyped) constants (ordinal, floating point,

nil-pointers typecasted to a class type, strings)
   o escape ", \, #10 and #13 in string constants as required by Java

git-svn-id: branches/jvmbackend@18391 -
This commit is contained in:
Jonas Maebe 2011-08-20 07:55:41 +00:00
parent 737f9f5e90
commit 8f2aacfed5
2 changed files with 196 additions and 58 deletions

View File

@ -53,11 +53,15 @@ interface
function VisibilityToStr(vis: tvisibility): string;
function MethodDefinition(pd: tprocdef): string;
function ConstValue(csym: tconstsym): ansistring;
function ConstAssignmentValue(csym: tconstsym): ansistring;
function ConstDefinition(sym: tconstsym): string;
function FieldDefinition(sym: tabstractvarsym): string;
function InnerObjDef(obj: tobjectdef): string;
procedure WriteProcDef(pd: tprocdef);
procedure WriteFieldSym(sym: tabstractvarsym);
procedure WriteConstSym(sym: tconstsym);
procedure WriteSymtableVarSyms(st: TSymtable);
procedure WriteSymtableProcdefs(st: TSymtable);
procedure WriteSymtableObjectDefs(st: TSymtable);
@ -96,7 +100,7 @@ implementation
cutils,cfileutl,systems,script,
fmodule,finput,verbose,
symtype,symtable,jvmdef,
itcpujas,cpubase,cgutils,
itcpujas,cpubase,cpuinfo,cgutils,
widestr
;
@ -130,6 +134,114 @@ implementation
fixline:=Copy(s,j,i-j+1);
end;
function constastr(p: pchar; len: longint): ansistring;
var
i,runstart,runlen: longint;
procedure flush;
begin
if runlen>0 then
begin
setlength(result,length(result)+runlen);
move(p[runstart],result[length(result)-runlen+1],runlen);
runlen:=0;
end;
end;
begin
result:='"';
runlen:=0;
runstart:=0;
for i:=0 to len-1 do
begin
{ escape control codes }
case p[i] of
{ LF and CR must be escaped specially, because \uXXXX parsing
happens in the pre-processor, so it's the same as actually
inserting a newline in the middle of a string constant }
#10:
begin
flush;
result:=result+'\n';
end;
#13:
begin
flush;
result:=result+'\r';
end;
'"','\':
begin
flush;
result:=result+'\'+p[i];
end
else if p[i]<#32 then
begin
flush;
result:=result+'\u'+hexstr(ord(p[i]),4);
end
else if p[i]<#127 then
begin
if runlen=0 then
runstart:=i;
inc(runlen);
end
else
// since Jasmin expects an UTF-16 string, we can't safely
// have high ASCII characters since they'll be
// re-interpreted as utf-16 anyway
internalerror(2010122808);
end;
end;
flush;
result:=result+'"';
end;
function constwstr(w: pcompilerwidechar; len: longint): ansistring;
var
i: longint;
begin
result:='"';
for i:=0 to len-1 do
begin
{ escape control codes }
case w[i] of
10:
result:=result+'\n';
13:
result:=result+'\r';
ord('"'),ord('\'):
result:=result+'\'+chr(w[i]);
else if (w[i]<32) or
(w[i]>127) then
result:=result+'\u'+hexstr(w[i],4)
else
result:=result+char(w[i]);
end;
end;
result:=result+'"';
end;
function constsingle(s: single): string;
begin
result:='0fx'+hexstr(longint(t32bitarray(s)),8);
end;
function constdouble(d: double): string;
begin
// force interpretation as double (since we write it out as an
// integer, we never have to swap the endianess). We have to
// include the sign separately because of the way Java parses
// hex numbers (0x8000000000000000 is not a valid long)
result:=hexstr(abs(int64(t64bitarray(d))),16);
if int64(t64bitarray(d))<0 then
result:='-'+result;
result:='0dx'+result;
end;
{****************************************************************************}
{ Jasmin Assembler writer }
{****************************************************************************}
@ -569,6 +681,72 @@ implementation
end;
function TJasminAssembler.ConstValue(csym: tconstsym): ansistring;
begin
case csym.consttyp of
constord:
{ always interpret as signed value, because the JVM does not
support unsigned 64 bit values }
result:=tostr(csym.value.valueord.svalue);
conststring:
result:=constastr(pchar(csym.value.valueptr),csym.value.len);
constreal:
case tfloatdef(csym.constdef).floattype of
s32real:
result:=constsingle(pbestreal(csym.value.valueptr)^);
s64real:
result:=constdouble(pbestreal(csym.value.valueptr)^);
else
internalerror(2011021204);
end;
constset:
result:='TODO: add support for constant sets';
constpointer:
{ can only be null, but that's the default value and should not
be written; there's no primitive type that can hold nill }
internalerror(2011021201);
constnil:
internalerror(2011021202);
constresourcestring:
result:='TODO: add support for constant resource strings';
constwstring:
result:=constwstr(pcompilerwidestring(csym.value.valueptr)^.data,pcompilerwidestring(csym.value.valueptr)^.len);
constguid:
result:='TODO: add support for constant guids';
else
internalerror(2011021205);
end;
end;
function TJasminAssembler.ConstAssignmentValue(csym: tconstsym): ansistring;
begin
{ nil is the default value -> don't write explicitly }
case csym.consttyp of
constpointer:
begin
if csym.value.valueordptr<>0 then
internalerror(2011021206);
result:='';
end;
constnil:
result:='';
else
result:=' = '+ConstValue(csym)
end;
end;
function TJasminAssembler.ConstDefinition(sym: tconstsym): string;
begin
result:=VisibilityToStr(sym.visibility);
{ formal constants are always class-level, not instance-level }
result:=result+'static final ';
result:=result+jvmmangledbasename(sym);
result:=result+ConstAssignmentValue(tconstsym(sym));
end;
function TJasminAssembler.FieldDefinition(sym: tabstractvarsym): string;
var
vissym: tabstractvarsym;
@ -596,7 +774,7 @@ implementation
result:='';
end;
fieldvarsym:
result:=VisibilityToStr(tfieldvarsym(vissym).visibility);
result:=VisibilityToStr(tstoredsym(vissym).visibility);
else
internalerror(2011011204);
end;
@ -661,6 +839,13 @@ implementation
end;
procedure TJasminAssembler.WriteConstSym(sym: tconstsym);
begin
AsmWrite('.field ');
AsmWriteln(ConstDefinition(sym));
end;
procedure TJasminAssembler.WriteSymtableVarSyms(st: TSymtable);
var
sym : tsym;
@ -677,6 +862,10 @@ implementation
begin
WriteFieldSym(tabstractvarsym(sym));
end;
constsym:
begin
WriteConstSym(tconstsym(sym));
end;
end;
end;
end;
@ -822,7 +1011,6 @@ implementation
function getopstr(const o:toper) : ansistring;
var
i,runstart,runlen: longint;
d: double;
s: single;
begin
@ -840,69 +1028,19 @@ implementation
getopstr:=getreferencestring(o.ref^);
top_single:
begin
s:=o.sval;
// force interpretation as single (since we write it out as an
// integer, we never have to swap the endianess).
result:='0fx'+hexstr(longint(t32bitarray(s)),8);
result:=constsingle(o.sval);
end;
top_double:
begin
d:=o.dval;
// force interpretation as double (since we write it out as an
// integer, we never have to swap the endianess). We have to
// include the sign separately because of the way Java parses
// hex numbers (0x8000000000000000 is not a valid long)
result:=hexstr(abs(int64(t64bitarray(d))),16);
if int64(t64bitarray(d))<0 then
result:='-'+result;
result:='0dx'+result;
result:=constdouble(o.dval);
end;
top_string:
begin
{ escape control codes }
runlen:=0;
runstart:=0;
for i:=1 to o.pcvallen do
begin
if o.pcval[i]<#32 then
begin
if runlen>0 then
begin
setlength(result,length(result)+runlen);
move(result[length(result)-runlen],o.pcval[runstart],runlen);
runlen:=0;
end;
result:=result+'\u'+hexstr(ord(o.pcval[i]),4);
end
else if o.pcval[i]<#127 then
begin
if runlen=0 then
runstart:=i;
inc(runlen);
end
else
// since Jasmin expects an UTF-16 string, we can't safely
// have high ASCII characters since they'll be
// re-interpreted as utf-16 anyway
internalerror(2010122808);
end;
if runlen>0 then
begin
setlength(result,length(result)+runlen);
move(result[length(result)-runlen],o.pcval[runstart],runlen);
end;
result:=constastr(o.pcval,o.pcvallen);
end;
top_wstring:
begin
{ escape control codes }
for i:=1 to getlengthwidestring(o.pwstrval) do
begin
if (o.pwstrval^.data[i]<32) or
(o.pwstrval^.data[i]>127) then
result:=result+'\u'+hexstr(o.pwstrval^.data[i],4)
else
result:=result+char(o.pwstrval^.data[i]);
end;
result:=constwstr(o.pwstrval^.data,getlengthwidestring(o.pwstrval));
end
else
internalerror(2010122802);

View File

@ -201,7 +201,7 @@ implementation
clearop(opidx);
pcvallen:=vallen;
getmem(pcval,vallen);
move(pcval^,pc^,vallen);
move(pc^,pcval^,vallen);
typ:=top_string;
end;
end;