hipe_rtl_binary_construct.erl

来自「OTP是开放电信平台的简称」· ERL 代码 · 共 1,132 行 · 第 1/3 页

ERL
1,132
字号
%% -*- erlang-indent-level: 2 -*-%% ====================================================================%%  Filename : 	hipe_rtl_inline_bs_ops.erl%%  Module   :	hipe_rtl_inline_bs_ops%%  Purpose  :  %%  Notes    : %%  History  :	*2001-06-14 Erik Johansson (happi@csd.uu.se): %%               Created.%%  CVS      :%%              $Author: kostis $%%              $Date: 2007/05/04 07:48:56 $%%              $Revision: 1.3 $%% ====================================================================%%  Exports  :%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%-module(hipe_rtl_binary_construct).-export([gen_rtl/6]).%%--------------------------------------------------------------------------include("../main/hipe.hrl").-include("hipe_rtl.hrl").-include("hipe_literals.hrl").-define(BYTE_SHIFT, 3). %% Turn bits into bytes or vice versa-define(LOW_BITS, 7). %% Three lowest bits set-define(BYTE_SIZE, 8).%% -------------------------------------------------------------------------%% The code is generated as a list of lists, it will be flattened later.%% gen_rtl(BsOP, Dst, Args, TrueLblName, FalseLblName, ConstTab) ->  %%io:format("~w, ~w, ~w~n", [BsOP, Args, Dst]),  case BsOP of    {bs_put_string, String, SizeInBytes} ->      [NewOffset] = get_real(Dst),      [Base, Offset] = Args,      put_string(NewOffset, ConstTab, String, SizeInBytes, Base, Offset, 		 TrueLblName);    _ ->       Code = 	case BsOP of	  bs_bits_to_bytes2 ->	    [Src]=Args,	    [Dst0]=Dst,	    SuccessLbl = hipe_rtl:mk_new_label(),	    Raw = hipe_rtl:mk_new_reg(),	    [hipe_tagscheme:test_fixnum(Src, hipe_rtl:label_name(SuccessLbl),				    FalseLblName, 0.99),	     SuccessLbl,	     hipe_tagscheme:untag_fixnum(Raw, Src),	     hipe_rtl:mk_alu(Raw, Raw, add, hipe_rtl:mk_imm(?LOW_BITS)),	     hipe_rtl:mk_alu(Raw, Raw, srl, hipe_rtl:mk_imm(?BYTE_SHIFT)),	     hipe_tagscheme:tag_fixnum(Dst0, Raw),	     hipe_rtl:mk_goto(TrueLblName)];	  bs_bits_to_bytes ->	    [Src] = Args,	    [Dst0] = Dst,	    SuccessLbl = hipe_rtl:mk_new_label(),	    NextLbl = hipe_rtl:mk_new_label(),	    Raw = hipe_rtl:mk_new_reg(),	    Tmp = hipe_rtl:mk_new_reg_gcsafe(),	    [hipe_tagscheme:test_fixnum(Src, hipe_rtl:label_name(SuccessLbl),					FalseLblName, 0.99),	     SuccessLbl,	     hipe_tagscheme:untag_fixnum(Raw, Src),	     hipe_rtl:mk_alub(Tmp, Raw, 'and', hipe_rtl:mk_imm(?LOW_BITS),eq,			      hipe_rtl:label_name(NextLbl),FalseLblName),	     NextLbl,	     hipe_rtl:mk_alu(Raw, Raw, srl, hipe_rtl:mk_imm(?BYTE_SHIFT)),	     hipe_tagscheme:tag_fixnum(Dst0, Raw),	     hipe_rtl:mk_goto(TrueLblName)];	  {bs_add, Const, Unit} ->	    Raw = hipe_rtl:mk_imm(Const),	    Tmp1 = hipe_rtl:mk_new_reg(),	    Tmp2 = hipe_rtl:mk_new_reg(),	    [New] = Args,	    [Dst0] = Dst,	    {SizeCode, SizeReg} = make_size(Unit, New, FalseLblName),	    SizeCode ++	      [hipe_rtl:mk_alu(Tmp1, SizeReg, add, Raw),	       hipe_tagscheme:tag_fixnum(Dst0, Tmp1),	       hipe_tagscheme:untag_fixnum(Tmp2, Dst0),	       hipe_rtl:mk_branch(Tmp1, eq, Tmp2, TrueLblName, FalseLblName)];	  	  {bs_add, Unit} ->	    Raw = hipe_rtl:mk_new_reg(),	    Tmp1 = hipe_rtl:mk_new_reg(),	    Tmp2 = hipe_rtl:mk_new_reg(),	    [Old, New] = Args,	    [Dst0] = Dst,	    {SizeCode, SizeReg} = make_size(Unit, New, FalseLblName),	    SizeCode ++	      [hipe_tagscheme:untag_fixnum(Raw, Old),	       hipe_rtl:mk_alu(Tmp1, SizeReg, add, Raw),	       hipe_tagscheme:tag_fixnum(Dst0, Tmp1),	       hipe_tagscheme:untag_fixnum(Tmp2, Dst0),	       hipe_rtl:mk_branch(Tmp1, eq, Tmp2, TrueLblName, FalseLblName)];	  	  {bs_init, Size, _Flags} -> 	    [] = Args,	    [Dst0, Base, Offset] = Dst,	    const_init2(Size, Dst0, Base, Offset, TrueLblName, FalseLblName);	  	  {bs_init, _Flags} -> 	    [Size] = Args,	    [Dst0, Base, Offset] = Dst,	    var_init2(Size, Dst0, Base, Offset, TrueLblName, FalseLblName);	 	  {bs_put_binary_all, _Flags} ->	    [Src, Base, Offset] = Args,	    [NewOffset] = get_real(Dst),	    put_binary_all(NewOffset, Src, Base, Offset, TrueLblName, FalseLblName);	   	  {bs_put_binary, Size, _Flags} ->	    [NewOffset] = get_real(Dst),	    case Args of	      [Src, Base, Offset] ->		put_static_binary(NewOffset, Src, Size, Base, Offset, 					    TrueLblName, FalseLblName);	      [Src, Bits, Base, Offset]  ->		{SizeCode, SizeReg} = make_size(Size, Bits, FalseLblName),		InCode = put_dynamic_binary(NewOffset, Src, SizeReg, Base, 					    Offset, TrueLblName, FalseLblName),		SizeCode ++ InCode	    end;			  {bs_put_float, Size, Flags, ConstInfo} ->    	    [NewOffset] = get_real(Dst),	    Aligned = aligned(Flags),	    LittleEndian = littleendian(Flags),	    case Args of	      [Src, Base, Offset] ->		CCode = static_float_c_code(NewOffset, Src, Base, Offset, Size, Flags, 					    TrueLblName, FalseLblName),		put_float(NewOffset, Src, Base, Offset, Size, CCode, Aligned, 			  LittleEndian, ConstInfo, TrueLblName);	      [Src, Bits, Base, Offset] ->		{SizeCode, SizeReg} = make_size(Size, Bits, FalseLblName),		InCode = float_c_code(NewOffset, Src, Base, Offset, SizeReg, 					    Flags, TrueLblName, FalseLblName),		SizeCode ++ InCode	    end;	  {bs_put_integer, Size, Flags, ConstInfo} ->	    Aligned = aligned(Flags),	    LittleEndian = littleendian(Flags),	    [NewOffset] = get_real(Dst),	    case ConstInfo of	      fail ->		[hipe_rtl:mk_goto(FalseLblName)];	      _ ->		case Args of		 [Src, Base, Offset]  ->		    CCode = static_int_c_code(NewOffset, Src, Base, Offset, Size, Flags, 					      TrueLblName, FalseLblName),		    put_static_int(NewOffset, Src, Base, Offset, Size, 						    CCode, Aligned, LittleEndian, 						    TrueLblName);		  [Src, Bits, Base, Offset] ->		    {SizeCode, SizeReg} = make_size(Size, Bits, FalseLblName),		    CCode = int_c_code(NewOffset, Src, Base, Offset, SizeReg, Flags, 					      TrueLblName, FalseLblName),		    InCode = 		      put_dynamic_int(NewOffset, Src, Base, Offset, 				      SizeReg, CCode, Aligned, 				      LittleEndian, TrueLblName),		    SizeCode ++ InCode		end	    end;    	  {unsafe_bs_put_integer, 0, _Flags, _ConstInfo} ->	    [NewOffset] = get_real(Dst),	    case Args of	      [_Src, _Base, Offset]  ->		[hipe_rtl:mk_move(NewOffset,Offset),		 hipe_rtl:mk_goto(TrueLblName)];	      [_Src, _Bits, _Base, Offset] ->		[hipe_rtl:mk_move(NewOffset,Offset),		 hipe_rtl:mk_goto(TrueLblName)]	    end;	    	  {unsafe_bs_put_integer, Size, Flags, ConstInfo} ->	    Aligned = aligned(Flags),	    LittleEndian = littleendian(Flags),	    [NewOffset] = get_real(Dst),	    case ConstInfo of	      fail ->		[hipe_rtl:mk_goto(FalseLblName)];	      _ ->		case Args of		 [Src, Base, Offset]  ->		    CCode = static_int_c_code(NewOffset, Src, Base, Offset, Size, Flags, 					      TrueLblName, FalseLblName),		    put_unsafe_static_int(NewOffset, Src, Base, Offset, Size, 					  CCode, Aligned, LittleEndian, 					  TrueLblName);		  [Src, Bits, Base, Offset] ->		    {SizeCode, SizeReg} = make_size(Size, Bits, FalseLblName),		    CCode = int_c_code(NewOffset, Src, Base, Offset, SizeReg, Flags, 					      TrueLblName, FalseLblName),		    InCode = 		      put_unsafe_dynamic_int(NewOffset, Src, Base, Offset, 					     SizeReg, CCode, Aligned, 					     LittleEndian, TrueLblName),		    SizeCode ++ InCode		end	    end; 	  bs_final ->	    [Src, Offset] = Args,	    BitSize = hipe_rtl:mk_new_reg(),	    ByteSize = hipe_rtl:mk_new_reg(),	    ShortLbl = hipe_rtl:mk_new_label(),	    LongLbl = hipe_rtl:mk_new_label(),	    case Dst of	      [DstVar] ->		[		 hipe_rtl:mk_alub(BitSize, Offset, 'and', hipe_rtl:mk_imm(?LOW_BITS),				 eq, hipe_rtl:label_name(ShortLbl), 				  hipe_rtl:label_name(LongLbl)),		 ShortLbl,		 hipe_rtl:mk_move(DstVar, Src),		 hipe_rtl:mk_goto(TrueLblName),		 %hipe_rtl:mk_goto(hipe_rtl:label_name(LongLbl)),		 LongLbl,		 hipe_rtl:mk_alu(ByteSize, Offset, srl, hipe_rtl:mk_imm(?BYTE_SHIFT)),		 hipe_tagscheme:unsafe_mk_sub_binary(DstVar, ByteSize, hipe_rtl:mk_imm(0),						   BitSize, hipe_rtl:mk_imm(0), Src),		 hipe_rtl:mk_goto(TrueLblName)]; 	      [] ->		[hipe_rtl:mk_goto(TrueLblName)]	    end	end,      {Code, ConstTab}  end.%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  Code that is used to create calls to beam functions%%%%  X_c_code/8, used for putting terms into binaries%%%%  X_get_c_code/10, used for getting terms from binaries%%%% - gen_test_sideffect_bs_call/4 is used to make a C-call that might%%       fail but doesn't return an erlang value.%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%static_float_c_code(NewOffset, Src, Base, Offset, Size, Flags, TrueLblName, 		    FalseLblName) ->   SizeReg = hipe_rtl:mk_new_reg(),  [hipe_rtl:mk_move(SizeReg, hipe_rtl:mk_imm(Size))|   float_c_code(NewOffset, Src, Base, Offset, SizeReg, Flags, TrueLblName, FalseLblName)].float_c_code(NewOffset, Src, Base, Offset, SizeReg, Flags, TrueLblName, FalseLblName) ->  put_c_code(bs_put_small_float, NewOffset, Src, Base, Offset, SizeReg, 	     Flags, TrueLblName, FalseLblName).static_int_c_code(NewOffset, Src, Base, Offset, Size, Flags, TrueLblName, 		    FalseLblName) ->  SizeReg = hipe_rtl:mk_new_reg(),  [hipe_rtl:mk_move(SizeReg, hipe_rtl:mk_imm(Size))|   int_c_code(NewOffset, Src, Base, Offset, SizeReg, Flags, TrueLblName, FalseLblName)].int_c_code(NewOffset, Src, Base, Offset, SizeReg, Flags, TrueLblName, FalseLblName) ->  put_c_code(bs_put_big_integer, NewOffset, Src, Base, Offset, SizeReg, 	     Flags, TrueLblName, FalseLblName).binary_c_code(NewOffset, Src, Base, Offset, Size, TrueLblName) ->  PassedLbl = hipe_rtl:mk_new_label(),  SizeReg = hipe_rtl:mk_new_reg(),  FlagsReg = hipe_rtl:mk_new_reg(),  [hipe_rtl:mk_move(FlagsReg, hipe_rtl:mk_imm(0)),   hipe_rtl:mk_move(SizeReg, Size),   hipe_rtl:mk_call([], bs_put_bits, [Src, SizeReg, Base, Offset, FlagsReg], 		    hipe_rtl:label_name(PassedLbl),[],not_remote),   PassedLbl,   hipe_rtl:mk_alu(NewOffset, Offset, add, SizeReg),   hipe_rtl:mk_goto(TrueLblName)].put_c_code(Func, NewOffset, Src, Base, Offset, SizeReg, Flags, TrueLblName, 	   FalseLblName) ->  PassedLbl = hipe_rtl:mk_new_label(),  FlagsReg = hipe_rtl:mk_new_reg(),  [hipe_rtl:mk_move(FlagsReg, hipe_rtl:mk_imm(Flags)),   gen_test_sideffect_bs_call(Func, [Src, SizeReg, Base, Offset, FlagsReg], 			      hipe_rtl:label_name(PassedLbl), FalseLblName),   PassedLbl,   hipe_rtl:mk_alu(NewOffset, Offset, add, SizeReg),   hipe_rtl:mk_goto(TrueLblName)].gen_test_sideffect_bs_call(Name,Args,TrueLblName,FalseLblName) ->  Tmp1 = hipe_rtl:mk_new_reg(),  RetLbl =  hipe_rtl:mk_new_label(),  [hipe_rtl:mk_call([Tmp1], Name, Args, hipe_rtl:label_name(RetLbl),[],not_remote),   RetLbl,   hipe_rtl:mk_branch(Tmp1, eq, hipe_rtl:mk_imm(0), 		      FalseLblName, TrueLblName, 0.01)].%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Small utility functions:%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%create_regs(X) when X > 0 ->  [hipe_rtl:mk_new_reg()|create_regs(X-1)];create_regs(0) ->  [].create_lbls(X) when X > 0 ->  [hipe_rtl:mk_new_label()|create_lbls(X-1)];create_lbls(0) ->  [].aligned(Flags) ->  case Flags band ?BSF_ALIGNED of    1 -> true;    0 -> false  end.littleendian(Flags) ->  case Flags band 2 of    2 -> true;    0 -> false  end.get_real([]) ->  [hipe_rtl:mk_new_reg()];get_real([NewOffset]) ->  [NewOffset].%%-----------------------------------------------------------------------------%% Help functions implementing the bs operations in rtl code.%%%% The following functions are called from the translation switch:%% %% - put_string/8 creates code to copy a string to a binary%%   starting at base+offset and ending at base+newoffset   %%%% - const_init2/6 initializes the creation of a binary of constant size%%      %% - var_init2/6 initializes the creation of a binary of variable size%%%% - get_int_from_unaligned_bin/11 creates code to extract a fixed%%       size integer from a binary or makes a c-call if it does not%%       conform to some certain rules.%%%% - get_unknown_size_int/11 creates code to extract a variable size%%       byte-aligned integer from a binary or makes a c-call if it%%       does not conform to some certain rules.%%%% - skip_no_of_bits/5 creates code to skip a variable amount of bits in a binary.%%%% - load_match_buffer/7 reloads the C-matchbuffer to RTL registers.%%%% - expand_runtime/4 creates code that calculates a maximal heap need%%       before a binary match%%%%-----------------------------------------------------------------------------put_string(NewOffset, ConstTab, String, SizeInBytes, Base, Offset, TLName) ->  [StringBase] = create_regs(1),  {NewTab, Lbl} = hipe_consttab:insert_block(ConstTab, byte, String),  {[hipe_rtl:mk_load_address(StringBase, Lbl, constant)|    copy_string(StringBase, SizeInBytes, Base, Offset, 		NewOffset, TLName)],   NewTab}.							  const_init2(Size, Dst, Base, Offset, TrueLblName, _FalseLblName) ->  Log2WordSize = hipe_rtl_arch:log2_word_size(),  WordSize = hipe_rtl_arch:word_size(),  NextLbl = hipe_rtl:mk_new_label(),

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?