mirror of
				https://gitlab.com/freepascal.org/fpc/source.git
				synced 2025-11-04 09:39:32 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			208 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
			
		
		
	
	
			208 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
{
 | 
						|
    Copyright (c) 2011 by Jonas Maebe
 | 
						|
 | 
						|
    Generates nodes for typed constant declarations
 | 
						|
 | 
						|
    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 njvmtcon;
 | 
						|
 | 
						|
{$i fpcdefs.inc}
 | 
						|
 | 
						|
interface
 | 
						|
 | 
						|
    uses
 | 
						|
      globtype,
 | 
						|
      node,
 | 
						|
      symtype,symdef,
 | 
						|
      ngtcon;
 | 
						|
 | 
						|
 | 
						|
    type
 | 
						|
      tarrstringdata = record
 | 
						|
        arrstring: ansistring;
 | 
						|
        arrdatastart, arrdatalen: asizeint;
 | 
						|
        arraybase: tnode;
 | 
						|
      end;
 | 
						|
 | 
						|
      tjvmtypedconstbuilder = class(tnodetreetypedconstbuilder)
 | 
						|
       private
 | 
						|
        procedure tc_flush_arr_strconst(def: tdef);
 | 
						|
       protected
 | 
						|
        arrstringdata: tarrstringdata;
 | 
						|
        parsingordarray: boolean;
 | 
						|
 | 
						|
        procedure parse_arraydef(def: tarraydef); override;
 | 
						|
        procedure tc_emit_setdef(def: tsetdef; var node: tnode);override;
 | 
						|
        procedure tc_emit_orddef(def: torddef; var node: tnode); override;
 | 
						|
      end;
 | 
						|
 | 
						|
implementation
 | 
						|
 | 
						|
    uses
 | 
						|
      globals,widestr,verbose,constexp,
 | 
						|
      defutil,
 | 
						|
      nbas,ncal,ncon,njvmcon;
 | 
						|
 | 
						|
 | 
						|
    procedure init_arrstringdata(out data: tarrstringdata);
 | 
						|
      begin
 | 
						|
        data.arrstring:='';
 | 
						|
        data.arrdatastart:=0;
 | 
						|
        data.arrdatalen:=0;
 | 
						|
        data.arraybase:=nil;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure tjvmtypedconstbuilder.tc_flush_arr_strconst(def: tdef);
 | 
						|
      var
 | 
						|
        wstr: pcompilerwidestring;
 | 
						|
        wc: tcompilerwidechar;
 | 
						|
        i: longint;
 | 
						|
        procvariant: string[8];
 | 
						|
      begin
 | 
						|
        // convert ansistring to packed unicodestring
 | 
						|
        initwidestring(wstr);
 | 
						|
        for i:=1 to length(arrstringdata.arrstring) div 2 do
 | 
						|
          begin
 | 
						|
            wc:=tcompilerwidechar(ord(arrstringdata.arrstring[i*2-1]) shl 8 or
 | 
						|
                                  ord(arrstringdata.arrstring[i*2]));
 | 
						|
            concatwidestringchar(wstr,wc);
 | 
						|
          end;
 | 
						|
        if odd(length(arrstringdata.arrstring)) then
 | 
						|
          concatwidestringchar(wstr,
 | 
						|
            tcompilerwidechar(ord(arrstringdata.arrstring[length(arrstringdata.arrstring)]) shl 8));
 | 
						|
 | 
						|
 | 
						|
        if is_signed(def) then
 | 
						|
          case def.size of
 | 
						|
            1: procvariant:='shortint';
 | 
						|
            2: procvariant:='smallint';
 | 
						|
            4: procvariant:='longint';
 | 
						|
            8: procvariant:='int64';
 | 
						|
            else
 | 
						|
              internalerror(2011111301);
 | 
						|
          end
 | 
						|
        else
 | 
						|
          case def.size of
 | 
						|
            1: procvariant:='byte';
 | 
						|
            2: procvariant:='word';
 | 
						|
            4: procvariant:='cardinal';
 | 
						|
            8: procvariant:='qword';
 | 
						|
            else
 | 
						|
              internalerror(2011111302);
 | 
						|
          end;
 | 
						|
        // (const s: unicodestring; var arr: array of shortint; startintdex, len: longint);
 | 
						|
        addstatement(statmnt,ccallnode.createintern('fpc_tcon_'+procvariant+'_array_from_string',
 | 
						|
          ccallparanode.create(genintconstnode(arrstringdata.arrdatalen),
 | 
						|
            ccallparanode.create(genintconstnode(arrstringdata.arrdatastart),
 | 
						|
              ccallparanode.create(arrstringdata.arraybase.getcopy,
 | 
						|
                ccallparanode.create(cstringconstnode.createunistr(wstr),nil))))));
 | 
						|
 | 
						|
        inc(arrstringdata.arrdatastart,arrstringdata.arrdatalen);
 | 
						|
        arrstringdata.arrstring:='';
 | 
						|
        arrstringdata.arrdatalen:=0;
 | 
						|
 | 
						|
        donewidestring(wstr);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure tjvmtypedconstbuilder.parse_arraydef(def: tarraydef);
 | 
						|
      var
 | 
						|
        old_arrstringdata: tarrstringdata;
 | 
						|
        old_parsingordarray: boolean;
 | 
						|
      begin
 | 
						|
        if is_dynamic_array(def) or
 | 
						|
           not is_integer(def.elementdef) or
 | 
						|
           not(ts_compact_int_array_init in current_settings.targetswitches) then
 | 
						|
          begin
 | 
						|
            inherited;
 | 
						|
            exit;
 | 
						|
          end;
 | 
						|
        old_arrstringdata:=arrstringdata;
 | 
						|
        init_arrstringdata(arrstringdata);
 | 
						|
        arrstringdata.arraybase:=basenode.getcopy;
 | 
						|
        old_parsingordarray:=parsingordarray;
 | 
						|
        parsingordarray:=true;
 | 
						|
        inherited;
 | 
						|
        if length(arrstringdata.arrstring)<>0 then
 | 
						|
          tc_flush_arr_strconst(def.elementdef);
 | 
						|
        arrstringdata.arraybase.free;
 | 
						|
        parsingordarray:=old_parsingordarray;
 | 
						|
        arrstringdata:=old_arrstringdata;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure tjvmtypedconstbuilder.tc_emit_setdef(def: tsetdef; var node: tnode);
 | 
						|
      begin
 | 
						|
        { indicate that set constant nodes have to be transformed into
 | 
						|
          constructors here }
 | 
						|
        if node.nodetype=setconstn then
 | 
						|
          tjvmsetconstnode(node).setconsttype:=sct_construct;
 | 
						|
        inherited tc_emit_setdef(def,node);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure tjvmtypedconstbuilder.tc_emit_orddef(def: torddef; var node: tnode);
 | 
						|
      var
 | 
						|
        elesize: longint;
 | 
						|
      begin
 | 
						|
        if not parsingordarray then
 | 
						|
          begin
 | 
						|
            inherited;
 | 
						|
            exit;
 | 
						|
          end;
 | 
						|
        if node.nodetype<>ordconstn then
 | 
						|
          internalerror(2011111101);
 | 
						|
        elesize:=def.size;
 | 
						|
        inc(arrstringdata.arrdatalen);
 | 
						|
        case elesize of
 | 
						|
          1:
 | 
						|
            arrstringdata.arrstring:=arrstringdata.arrstring+char(tordconstnode(node).value.svalue);
 | 
						|
          2:
 | 
						|
            arrstringdata.arrstring:=arrstringdata.arrstring+char(tordconstnode(node).value.svalue shr 8)+char(tordconstnode(node).value.svalue and $ff);
 | 
						|
          4:
 | 
						|
            arrstringdata.arrstring:=arrstringdata.arrstring+char((tordconstnode(node).value.svalue shr 24))+
 | 
						|
              char((tordconstnode(node).value.svalue shr 16) and $ff)+
 | 
						|
              char((tordconstnode(node).value.svalue shr 8) and $ff)+
 | 
						|
              char(tordconstnode(node).value.svalue and $ff);
 | 
						|
          8:
 | 
						|
            arrstringdata.arrstring:=arrstringdata.arrstring+char((tordconstnode(node).value.svalue shr 56))+
 | 
						|
              char((tordconstnode(node).value.svalue shr 48) and $ff)+
 | 
						|
              char((tordconstnode(node).value.svalue shr 40) and $ff)+
 | 
						|
              char((tordconstnode(node).value.svalue shr 32) and $ff)+
 | 
						|
              char((tordconstnode(node).value.svalue shr 24) and $ff)+
 | 
						|
              char((tordconstnode(node).value.svalue shr 16) and $ff)+
 | 
						|
              char((tordconstnode(node).value.svalue shr 8) and $ff)+
 | 
						|
              char(tordconstnode(node).value.svalue and $ff);
 | 
						|
        end;
 | 
						|
        { we can't use the full 64kb, because inside the Java class file the
 | 
						|
          string constant is actually encoded using UTF-8 and it's this UTF-8
 | 
						|
          encoding that has to fit inside 64kb (and utf-8 encoding of random
 | 
						|
          data can easily blow up its size by about a third) }
 | 
						|
        if length(arrstringdata.arrstring)>40000 then
 | 
						|
          tc_flush_arr_strconst(def);
 | 
						|
        basenode.free;
 | 
						|
        basenode:=nil;
 | 
						|
        node.free;
 | 
						|
        node:=nil;
 | 
						|
      end;
 | 
						|
 | 
						|
begin
 | 
						|
  ctypedconstbuilder:=tjvmtypedconstbuilder;
 | 
						|
end.
 |