123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818 |
- {
- Copyright (c) 1998-2011 by Florian Klaempfl and Jonas Maebe
- Generate JVM inline nodes
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- ****************************************************************************
- }
- unit njvminl;
- {$i fpcdefs.inc}
- interface
- uses
- cpubase,
- node,ninl,ncginl;
- type
- tjvminlinenode = class(tcginlinenode)
- protected
- function typecheck_length(var handled: boolean): tnode;
- function typecheck_high(var handled: boolean): tnode;
- function typecheck_new(var handled: boolean): tnode;
- function first_copy: tnode; override;
- function first_assigned: tnode; override;
- function first_get_frame: tnode; override;
- function first_box: tnode; override;
- function first_unbox: tnode; override;
- function first_setlength_array: tnode;
- public
- { typecheck override to intercept handling }
- function pass_typecheck: tnode; override;
- { first pass override
- so that the code generator will actually generate
- these nodes.
- }
- function first_sqr_real: tnode; override;
- function first_trunc_real: tnode; override;
- function first_new: tnode; override;
- function first_IncludeExclude: tnode; override;
- function first_setlength: tnode; override;
- function first_length: tnode; override;
- procedure second_length; override;
- procedure second_sqr_real; override;
- procedure second_trunc_real; override;
- procedure second_new; override;
- procedure second_setlength; override;
- protected
- procedure load_fpu_location;
- end;
- implementation
- uses
- cutils,globals,verbose,globtype,constexp,fmodule,compinnr,
- aasmbase,aasmtai,aasmdata,aasmcpu,
- symtype,symconst,symdef,symsym,symcpu,symtable,jvmdef,
- defutil,
- nadd,nbas,ncon,ncnv,nmat,nmem,ncal,nld,nflw,nutils,
- cgbase,pass_1,pass_2,
- cpuinfo,ncgutil,
- cgutils,hlcgobj,hlcgcpu;
- {*****************************************************************************
- tjvminlinenode
- *****************************************************************************}
- function tjvminlinenode.typecheck_length(var handled: boolean): tnode;
- begin
- result:=nil;
- typecheckpass(left);
- if is_open_array(left.resultdef) or
- is_dynamic_array(left.resultdef) or
- is_array_of_const(left.resultdef) then
- begin
- resultdef:=s32inttype;
- handled:=true;
- end;
- end;
- function tjvminlinenode.typecheck_high(var handled: boolean): tnode;
- begin
- result:=nil;
- typecheckpass(left);
- if is_dynamic_array(left.resultdef) or
- is_open_array(left.resultdef) or
- is_array_of_const(left.resultdef) then
- begin
- { replace with pred(length(arr)) }
- result:=cinlinenode.create(in_pred_x,false,
- cinlinenode.create(in_length_x,false,left));
- left:=nil;
- handled:=true;
- end;
- end;
- function tjvminlinenode.typecheck_new(var handled: boolean): tnode;
- var
- para: tcallparanode;
- elemdef: tdef;
- begin
- result:=nil;
- { normally never exists; used by the JVM backend to create new
- arrays because it requires special opcodes }
- tcallparanode(left).get_paratype;
- if is_dynamic_array(left.resultdef) then
- begin
- para:=tcallparanode(left);
- { need at least one extra parameter in addition to the
- array }
- if not assigned(para.right) then
- internalerror(2011012206);
- elemdef:=tarraydef(left.resultdef).elementdef;
- while elemdef.typ=arraydef do
- begin
- { if we have less length specifiers than dimensions, make
- the last array an array of length 0 }
- if not assigned(para.right) then
- begin
- para.right:=ccallparanode.create(
- cordconstnode.create(0,s32inttype,false),nil);
- tcallparanode(para.right).get_paratype;
- break;
- end
- else
- begin
- inserttypeconv(tcallparanode(para.right).left,s32inttype);
- tcallparanode(para.right).get_paratype;
- end;
- para:=tcallparanode(para.right);
- elemdef:=tarraydef(elemdef).elementdef;
- end;
- resultdef:=left.resultdef;
- handled:=true;
- end;
- end;
- function tjvminlinenode.first_copy: tnode;
- var
- ppn: tcallparanode;
- arr, len, start: tnode;
- eledef: tdef;
- counter, ndims: longint;
- finaltype: char;
- begin
- if is_dynamic_array(resultdef) then
- begin
- ppn:=tcallparanode(left);
- counter:=1;
- while assigned(ppn.right) do
- begin
- inc(counter);
- ppn:=tcallparanode(ppn.right);
- end;
- if (counter=3) then
- begin
- len:=tcallparanode(left).left;
- tcallparanode(left).left:=nil;
- start:=tcallparanode(tcallparanode(left).right).left;
- tcallparanode(tcallparanode(left).right).left:=nil;
- { free the original start/len paras and remove them }
- ppn:=tcallparanode(left);
- left:=tcallparanode(tcallparanode(left).right).right;
- tcallparanode(ppn.right).right:=nil;
- ppn.free;
- end
- else
- begin
- { use special -1,-1 argument to copy the whole array }
- len:=genintconstnode(-1);
- start:=genintconstnode(-1);
- end;
- { currently there is one parameter left: the array itself }
- arr:=tcallparanode(left).left;
- tcallparanode(left).left:=nil;
- { in case it's a dynamic array of static arrays, get the dimensions
- of the static array components }
- eledef:=tarraydef(resultdef).elementdef;
- ndims:=1;
- while (eledef.typ=arraydef) and
- not is_dynamic_array(eledef) do
- begin
- inc(ndims);
- eledef:=tarraydef(eledef).elementdef;
- end;
- { get the final element kind }
- finaltype:=jvmarrtype_setlength(eledef);
- { construct the call to
- fpc_dynarray_copy(src: JLObject; start, len: longint; ndim: longint; eletype: jchar) }
- result:=ccallnode.createintern('FPC_DYNARRAY_COPY',
- ccallparanode.create(cordconstnode.create(ord(finaltype),cwidechartype,false),
- ccallparanode.create(genintconstnode(ndims),
- ccallparanode.create(len,
- ccallparanode.create(start,
- ccallparanode.create(ctypeconvnode.create_explicit(arr,java_jlobject),nil)
- )
- )
- )
- )
- );
- inserttypeconv_explicit(result,resultdef);
- end
- else
- result:=inherited first_copy;
- end;
- function tjvminlinenode.first_assigned: tnode;
- begin
- { on the JVM target, empty arrays can also be <> nil but have length 0
- instead. Since assigned(dynarray) is only used to determine whether
- the length is <> 0 on other targets, replace this expression here }
- if is_dynamic_array(tcallparanode(left).left.resultdef) then
- begin
- result:=caddnode.create(unequaln,cinlinenode.create(
- in_length_x,false,tcallparanode(left).left),genintconstnode(0));
- tcallparanode(left).left:=nil;
- end
- else
- result:=inherited;
- end;
- function tjvminlinenode.first_get_frame: tnode;
- begin
- { no frame pointer on the JVM target }
- result:=cnilnode.create;
- end;
- function tjvminlinenode.first_box: tnode;
- var
- boxdef,
- boxparadef: tdef;
- begin
- { get class wrapper type }
- jvmgetboxtype(left.resultdef,boxdef,boxparadef,true);
- { created wrapped instance }
- inserttypeconv_explicit(tcallparanode(left).left,boxparadef);
- result:=ccallnode.createinternmethod(
- cloadvmtaddrnode.create(ctypenode.create(tobjectdef(boxdef))),'CREATE',left);
- { reused }
- left:=nil;
- end;
- function tjvminlinenode.first_unbox: tnode;
- var
- val: tnode;
- boxdef,
- boxparadef: tdef;
- begin
- jvmgetboxtype(resultdef,boxdef,boxparadef,true);
- val:=tcallparanode(tcallparanode(left).right).left;
- tcallparanode(tcallparanode(left).right).left:=nil;
- { typecast to the boxing type }
- val:=ctypeconvnode.create_explicit(val,boxdef);
- { call the unboxing method }
- val:=ccallnode.createinternmethod(val,jvmgetunboxmethod(resultdef),nil);
- { add type conversion for shortint -> byte etc }
- inserttypeconv_explicit(val,resultdef);
- result:=val;
- end;
- function tjvminlinenode.pass_typecheck: tnode;
- var
- handled: boolean;
- begin
- result:=nil;
- handled:=false;
- case inlinenumber of
- in_length_x:
- begin
- result:=typecheck_length(handled);
- end;
- in_high_x:
- begin
- result:=typecheck_high(handled);
- end;
- in_new_x:
- begin
- result:=typecheck_new(handled);
- end;
- in_sizeof_x:
- begin
- { can't get the size of the data of a class/object }
- if left.resultdef.typ in [objectdef,classrefdef] then
- Message(parser_e_illegal_expression);
- end;
- else
- ;
- end;
- if not handled then
- result:=inherited pass_typecheck;
- end;
- (*
- function tjvminlinenode.first_sqrt_real : tnode;
- begin
- if (current_settings.cputype >= cpu_PPC970) then
- begin
- expectloc:=LOC_FPUREGISTER;
- first_sqrt_real := nil;
- end
- else
- result:=inherited first_sqrt_real;
- end;
- *)
- function tjvminlinenode.first_sqr_real : tnode;
- begin
- expectloc:=LOC_FPUREGISTER;
- first_sqr_real:=nil;
- end;
- function tjvminlinenode.first_trunc_real : tnode;
- begin
- expectloc:=LOC_REGISTER;
- first_trunc_real:=nil;
- end;
- function tjvminlinenode.first_new: tnode;
- begin
- { skip the array; it's a type node }
- tcallparanode(tcallparanode(left).right).firstcallparan;
- expectloc:=LOC_REGISTER;
- result:=nil;
- end;
- function tjvminlinenode.first_IncludeExclude: tnode;
- var
- setpara: tnode;
- valuepara: tcallparanode;
- seteledef: tdef;
- procname: string[6];
- begin
- setpara:=tcallparanode(left).left;
- tcallparanode(left).left:=nil;
- valuepara:=tcallparanode(tcallparanode(left).right);
- tcallparanode(left).right:=nil;
- seteledef:=tsetdef(setpara.resultdef).elementdef;
- setpara:=caddrnode.create_internal(setpara);
- include(taddrnode(setpara).addrnodeflags,anf_typedaddr);
- if seteledef.typ=enumdef then
- begin
- inserttypeconv_explicit(setpara,java_juenumset);
- inserttypeconv_explicit(valuepara.left,tcpuenumdef(tenumdef(seteledef).getbasedef).classdef);
- end
- else
- begin
- inserttypeconv_explicit(setpara,java_jubitset);
- inserttypeconv_explicit(valuepara.left,s32inttype);
- end;
- if inlinenumber=in_include_x_y then
- procname:='ADD'
- else
- procname:='REMOVE';
- result:=ccallnode.createinternmethod(setpara,procname,valuepara);
- end;
- function tjvminlinenode.first_setlength_array: tnode;
- var
- assignmenttarget,
- ppn,
- newparas: tnode;
- newnode: tnode;
- eledef,
- objarraydef: tdef;
- ndims: longint;
- finaltype: char;
- setlenroutine: string;
- lefttemp: ttempcreatenode;
- newblock: tblocknode;
- newstatement: tstatementnode;
- begin
- { first parameter is the array, the rest are the dimensions }
- newparas:=tcallparanode(left).right;
- tcallparanode(left).right:=nil;
- { count the number of specified dimensions, and determine the type of
- the final one }
- ppn:=newparas;
- eledef:=tarraydef(left.resultdef).elementdef;
- { ppn already points to the first dimension }
- ndims:=1;
- while assigned(tcallparanode(ppn).right) do
- begin
- inc(ndims);
- eledef:=tarraydef(eledef).elementdef;
- ppn:=tcallparanode(ppn).right;
- end;
- { in case it's a dynamic array of static arrays, we must also allocate
- the static arrays! }
- while (eledef.typ=arraydef) and
- not is_dynamic_array(eledef) do
- begin
- inc(ndims);
- tcallparanode(ppn).right:=
- ccallparanode.create(
- genintconstnode(tarraydef(eledef).elecount),nil);
- ppn:=tcallparanode(ppn).right;
- eledef:=tarraydef(eledef).elementdef;
- end;
- { prepend type parameter for the array }
- newparas:=ccallparanode.create(ctypenode.create(left.resultdef),newparas);
- ttypenode(tcallparanode(newparas).left).allowed:=true;
- { node to create the new array }
- newnode:=cinlinenode.create(in_new_x,false,newparas);
- { Common parameters for setlength helper }
- { start with org (save assignmenttarget itself to assign the result back to) }
- { store left into a temp in case it may contain a function call
- (which must not be evaluated twice) }
- newblock:=nil;
- newstatement:=nil;
- lefttemp:=maybereplacewithtempref(tcallparanode(left).left,newblock,newstatement,tcallparanode(left).left.resultdef.size,false);
- if assigned(lefttemp) then
- begin
- assignmenttarget:=ctemprefnode.create(lefttemp);
- typecheckpass(tnode(assignmenttarget));
- end
- else
- assignmenttarget:=tcallparanode(left).left.getcopy;
- newparas:=left;
- left:=nil;
- finaltype:=jvmarrtype_setlength(eledef);
- { since the setlength prototypes require certain types, insert
- explicit type conversions where necessary }
- objarraydef:=nil;
- if (ndims>1) then
- begin
- { expects array of JLObject }
- setlenroutine:='FPC_SETLENGTH_DYNARR_MULTIDIM';
- objarraydef:=search_system_type('TJOBJECTARRAY').typedef
- end
- else
- begin
- case finaltype of
- 'R':
- begin
- { expects array of FpcBaseRecord}
- setlenroutine:='FPC_SETLENGTH_DYNARR_JRECORD';
- objarraydef:=search_system_type('TJRECORDARRAY').typedef;
- end;
- 'T':
- begin
- { expects array of ShortstringClass}
- setlenroutine:='FPC_SETLENGTH_DYNARR_JSHORTSTRING';
- objarraydef:=search_system_type('TSHORTSTRINGARRAY').typedef;
- end;
- else
- begin
- { expects JLObject }
- setlenroutine:='FPC_SETLENGTH_DYNARR_GENERIC';
- objarraydef:=java_jlobject;
- end
- end;
- end;
- tcallparanode(newparas).left:=ctypeconvnode.create_explicit(tcallparanode(newparas).left,objarraydef);
- newnode:=ctypeconvnode.create_explicit(newnode,objarraydef);
- { prepend new }
- newparas:=ccallparanode.create(newnode,newparas);
- { prepend deepcopy }
- newparas:=ccallparanode.create(cordconstnode.create(0,pasbool1type,false),newparas);
- { call the right setlenght helper }
- if ndims>1 then
- begin
- { create proper parameters, from right to left:
- eletype=finaltype, ndim=ndims, deepcopy=false, new=newnode,
- assignmenttarget=tcallparanode(left).left }
- { prepend ndim }
- newparas:=ccallparanode.create(cordconstnode.create(ndims,s32inttype,false),newparas);
- { prepend eletype }
- newparas:=ccallparanode.create(cordconstnode.create(ord(finaltype),cwidechartype,false),newparas);
- end
- else
- begin
- { create proper parameters, from right to left:
- deepcopy=false, new=newnode, assignmenttarget=tcallparnode(left).left
- -> already done in common part above }
- end;
- result:=ccallnode.createintern(setlenroutine,newparas);
- { assign result back to org (no call-by-reference for Java) }
- result:=cassignmentnode.create(assignmenttarget,
- ctypeconvnode.create_explicit(result,assignmenttarget.resultdef));
- if assigned(lefttemp) then
- begin
- addstatement(newstatement,result);
- addstatement(newstatement,ctempdeletenode.create(lefttemp));
- result:=newblock;
- end;
- end;
- function tjvminlinenode.first_setlength: tnode;
- begin
- { reverse the parameter order so we can process them more easily }
- reverseparameters(tcallparanode(left));
- { treat setlength(x,0) specially: used to init uninitialised locations }
- if not is_shortstring(left.resultdef) and
- not assigned(tcallparanode(tcallparanode(left).right).right) and
- is_constintnode(tcallparanode(tcallparanode(left).right).left) and
- (tordconstnode(tcallparanode(tcallparanode(left).right).left).value=0) then
- begin
- result:=nil;
- expectloc:=LOC_VOID;
- exit;
- end;
- { strings are handled the same as on other platforms }
- if left.resultdef.typ=stringdef then
- begin
- reverseparameters(tcallparanode(left));
- result:=inherited first_setlength;
- exit;
- end;
- case left.resultdef.typ of
- arraydef:
- result:=first_setlength_array;
- else
- internalerror(2011031204);
- end;
- end;
- function tjvminlinenode.first_length: tnode;
- var
- newblock: tblocknode;
- newstatement: tstatementnode;
- lefttemp,
- lentemp: ttempcreatenode;
- ifcond,
- stringtemp,
- stringnonnull,
- stringnull: tnode;
- psym: tsym;
- stringclass: tdef;
- begin
- if is_wide_or_unicode_string(left.resultdef) or
- is_ansistring(left.resultdef) then
- begin
- { if assigned(stringclass(left)) then
- lentemp:=stringclass(left).length()
- else
- lentemp:=0;
- --> return lentemp
- }
- if is_ansistring(left.resultdef) then
- stringclass:=java_ansistring
- else
- stringclass:=java_jlstring;
- newblock:=internalstatements(newstatement);
- { store left into a temp since it may contain a function call
- (which must not be evaluated twice) }
- if node_complexity(left)>4 then
- begin
- lefttemp:=ctempcreatenode.create_value(stringclass,stringclass.size,tt_persistent,true,ctypeconvnode.create_explicit(left,stringclass));
- addstatement(newstatement,lefttemp);
- stringtemp:=ctemprefnode.create(lefttemp)
- end
- else
- begin
- lefttemp:=nil;
- stringtemp:=ctypeconvnode.create_explicit(left,stringclass);
- end;
- left:=nil;
- lentemp:=ctempcreatenode.create(s32inttype,s32inttype.size,tt_persistent,true);
- addstatement(newstatement,lentemp);
- { if-condition: assigned(stringclass(stringvar))? }
- ifcond:=cinlinenode.create(in_assigned_x,false,
- ccallparanode.create(stringtemp.getcopy,nil));
- { then-path: call length() method }
- psym:=search_struct_member(tabstractrecorddef(stringclass),'LENGTH');
- if not assigned(psym) or
- (psym.typ<>procsym) then
- internalerror(2011031403);
- stringnonnull:=cassignmentnode.create(
- ctemprefnode.create(lentemp),
- ccallnode.create(nil,tprocsym(psym),psym.owner,stringtemp,[],nil));
- { else-path: length is 0 }
- stringnull:=cassignmentnode.create(
- ctemprefnode.create(lentemp),
- genintconstnode(0));
- { complete if-statement }
- addstatement(newstatement,cifnode.create(ifcond,stringnonnull,stringnull));
- { free lefttemp }
- if assigned(lefttemp) then
- addstatement(newstatement,ctempdeletenode.create(lefttemp));
- { return len temp }
- addstatement(newstatement,ctempdeletenode.create_normal_temp(lentemp));
- addstatement(newstatement,ctemprefnode.create(lentemp));
- result:=newblock;
- end
- else if is_shortstring(left.resultdef) then
- begin
- psym:=search_struct_member(tabstractrecorddef(java_shortstring),'LENGTH');
- if not assigned(psym) or
- (psym.typ<>procsym) then
- internalerror(2011052402);
- result:=
- ccallnode.create(nil,tprocsym(psym),psym.owner,
- ctypeconvnode.create_explicit(caddrnode.create_internal(left),java_shortstring),[],nil);
- { reused }
- left:=nil;
- end
- { should be no other string types }
- else if left.resultdef.typ=stringdef then
- internalerror(2011052403)
- else
- result:=inherited first_length;
- end;
- procedure tjvminlinenode.second_length;
- begin
- if is_dynamic_array(left.resultdef) or
- is_open_array(left.resultdef) or
- is_array_of_const(left.resultdef) then
- begin
- location_reset(location,LOC_REGISTER,OS_S32);
- location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,s32inttype);
- secondpass(left);
- thlcgjvm(hlcg).g_getarraylen(current_asmdata.CurrAsmList,left.location);
- thlcgjvm(hlcg).a_load_stack_reg(current_asmdata.CurrAsmList,resultdef,location.register);
- end
- else
- internalerror(2011012004);
- end;
- (*
- function tjvminlinenode.first_round_real : tnode;
- begin
- if (current_settings.cputype >= cpu_PPC970) then
- begin
- expectloc:=LOC_REFERENCE;
- first_round_real := nil;
- end
- else
- result:=inherited first_round_real;
- end;
- *)
- { load the FPU value on the evaluation stack }
- procedure tjvminlinenode.load_fpu_location;
- begin
- secondpass(left);
- thlcgjvm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,left.resultdef,left.location);
- end;
- (*
- procedure tjvminlinenode.second_sqrt_real;
- begin
- if (current_settings.cputype < cpu_PPC970) then
- internalerror(2007020910);
- location.loc:=LOC_FPUREGISTER;
- load_fpu_location;
- case left.location.size of
- OS_F32:
- current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FSQRTS,location.register,
- left.location.register));
- OS_F64:
- current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FSQRT,location.register,
- left.location.register));
- else
- inherited;
- end;
- end;
- *)
- procedure tjvminlinenode.second_sqr_real;
- begin
- load_fpu_location;
- location_reset(location,LOC_FPUREGISTER,location.size);
- location.register:=hlcg.getfpuregister(current_asmdata.CurrAsmList,resultdef);
- case left.location.size of
- OS_F32:
- begin
- current_asmdata.CurrAsmList.concat(taicpu.op_none(a_dup));
- thlcgjvm(hlcg).incstack(current_asmdata.CurrAsmList,1);
- current_asmdata.CurrAsmList.concat(taicpu.op_none(a_fmul));
- thlcgjvm(hlcg).decstack(current_asmdata.CurrAsmList,1);
- end;
- OS_F64:
- begin
- current_asmdata.CurrAsmList.concat(taicpu.op_none(a_dup2));
- thlcgjvm(hlcg).incstack(current_asmdata.CurrAsmList,2);
- current_asmdata.CurrAsmList.concat(taicpu.op_none(a_dmul));
- thlcgjvm(hlcg).decstack(current_asmdata.CurrAsmList,2);
- end;
- else
- internalerror(2011010804);
- end;
- thlcgjvm(hlcg).a_load_stack_reg(current_asmdata.CurrAsmList,resultdef,location.register);
- end;
- procedure tjvminlinenode.second_trunc_real;
- begin
- load_fpu_location;
- location_reset(location,LOC_REGISTER,left.location.size);
- location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef);
- case left.location.size of
- OS_F32:
- begin
- current_asmdata.CurrAsmList.concat(taicpu.op_none(a_f2l));
- { 32 bit float -> 64 bit int: +1 stack slot }
- thlcgjvm(hlcg).incstack(current_asmdata.CurrAsmList,1);
- end;
- OS_F64:
- begin
- { 64 bit float -> 64 bit int: same number of stack slots }
- current_asmdata.CurrAsmList.concat(taicpu.op_none(a_d2l));
- end;
- else
- internalerror(2011010805);
- end;
- thlcgjvm(hlcg).a_load_stack_reg(current_asmdata.CurrAsmList,resultdef,location.register);
- end;
- procedure tjvminlinenode.second_new;
- var
- arr: tnode;
- hp: tcallparanode;
- paracount: longint;
- begin
- hp:=tcallparanode(left);
- { we don't second pass this one, it's only a type node }
- arr:=hp.left;
- if not is_dynamic_array(arr.resultdef) then
- internalerror(2011012204);
- hp:=tcallparanode(hp.right);
- if not assigned(hp) then
- internalerror(2011012205);
- paracount:=0;
- { put all the dimensions on the stack }
- repeat
- inc(paracount);
- secondpass(hp.left);
- thlcgjvm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,hp.left.resultdef,hp.left.location);
- hp:=tcallparanode(hp.right);
- until not assigned(hp);
- { create the array }
- thlcgjvm(hlcg).g_newarray(current_asmdata.CurrAsmList,arr.resultdef,paracount);
- location_reset(location,LOC_REGISTER,OS_ADDR);
- location.register:=hlcg.getaddressregister(current_asmdata.CurrAsmList,resultdef);
- thlcgjvm(hlcg).a_load_stack_reg(current_asmdata.CurrAsmList,arr.resultdef,location.register);
- end;
- procedure tjvminlinenode.second_setlength;
- var
- target: tnode;
- lenpara: tnode;
- emptystr: ansichar;
- tmpreg: tregister;
- begin
- target:=tcallparanode(left).left;
- lenpara:=tcallparanode(tcallparanode(left).right).left;
- if assigned(tcallparanode(tcallparanode(left).right).right) or
- not is_constintnode(lenpara) or
- (tordconstnode(lenpara).value<>0) then
- internalerror(2011031801);
- secondpass(target);
- { can't directly load from stack to destination, because if target is
- a reference then its address must be placed on the stack before the
- value }
- tmpreg:=hlcg.getaddressregister(current_asmdata.CurrAsmList,target.resultdef);
- if is_wide_or_unicode_string(target.resultdef) then
- begin
- emptystr:=#0;
- current_asmdata.CurrAsmList.concat(taicpu.op_string(a_ldc,0,@emptystr));
- thlcgjvm(hlcg).incstack(current_asmdata.CurrAsmList,1);
- end
- else if is_ansistring(target.resultdef) then
- thlcgjvm(hlcg).a_load_const_stack(current_asmdata.CurrAsmList,java_jlobject,0,R_ADDRESSREGISTER)
- else if is_dynamic_array(target.resultdef) then
- begin
- thlcgjvm(hlcg).a_load_const_stack(current_asmdata.CurrAsmList,s32inttype,0,R_INTREGISTER);
- thlcgjvm(hlcg).g_newarray(current_asmdata.CurrAsmList,target.resultdef,1);
- end
- else
- internalerror(2011031401);
- thlcgjvm(hlcg).a_load_stack_reg(current_asmdata.CurrAsmList,target.resultdef,tmpreg);
- thlcgjvm(hlcg).a_load_reg_loc(current_asmdata.CurrAsmList,target.resultdef,target.resultdef,tmpreg,target.location);
- end;
- begin
- cinlinenode:=tjvminlinenode;
- end.
|