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 + -
显示快捷键?