firefly
firefly copied to clipboard
Subbinaries are being stored as HeapBinary in compiled code
Subbinaries are being stored as HeapBinary in compiled code, so that the bit-count is lost.
init.erl
-module(init).
-export([start/0]).
-import(erlang, [binary_part/2, byte_size/1, display/1]).
start() ->
Binary = <<0, 1, 2, 3 : 2>>,
Start = 0,
FullByteCount = bit_size(Binary) div 8,
Length = FullByteCount,
StartLength = {Start, Length},
display(bit_size(Binary)),
display(Binary),
display(StartLength),
BinaryPart = binary_part(Binary, StartLength),
display(BinaryPart).
native_implemented/otp/lib/erlang/bit_size_1.rs
With modifications these modifications to show the type of the binary passed to bit_size/1
#[cfg(all(not(target_arch = "wasm32"), test))]
mod test;
use anyhow::*;
use liblumen_alloc::erts::exception;
use liblumen_alloc::erts::process::Process;
use liblumen_alloc::erts::term::prelude::*;
#[native_implemented::function(erlang:bit_size/1)]
pub fn result(process: &Process, bitstring: Term) -> exception::Result<Term> {
let option_total_bit_len = match bitstring.decode()? {
TypedTerm::BinaryLiteral(binary_literal) => {
println!("{} is a binary literal", bitstring);
Some(binary_literal.total_bit_len())
},
TypedTerm::HeapBinary(heap_binary) => {
println!("{} is a heap binary", bitstring);
Some(heap_binary.total_bit_len())
},
TypedTerm::ProcBin(process_binary) => {
println!("{} is a procbin", bitstring);
Some(process_binary.total_bit_len())
},
TypedTerm::SubBinary(subbinary) => {
println!("{} is a subbinary", bitstring);
Some(subbinary.total_bit_len())
},
TypedTerm::MatchContext(match_context) => Some(match_context.total_bit_len()),
_ => None,
};
match option_total_bit_len {
Some(total_bit_len) => Ok(process.integer(total_bit_len)?),
None => Err(TypeError)
.context(format!("bitstring ({}) is not a bitstring", bitstring))
.map_err(From::from),
}
}
STDER
---- erlang::binary_part_2::with_bitstring::with_tuple_with_arity_2::with_bit_count::with_zero_start_and_byte_count_length_returns_subbinary_without_bit_count stdout ----
thread 'erlang::binary_part_2::with_bitstring::with_tuple_with_arity_2::with_bit_count::with_zero_start_and_byte_count_length_returns_subbinary_without_bit_count' panicked at 'assertion failed: `(left == right)`
left: `"<<0, 1, 2, 192>> is a heap binary\n<<0, 1, 2, 192>> is a heap binary\n32\n<<0, 1, 2, 192>>\n{0, 4}\n<<0, 1, 2, 192>>\n"`,
right: `"<<0,1,2>>\n"`:
stdout = <<0, 1, 2, 192>> is a heap binary
<<0, 1, 2, 192>> is a heap binary
32
<<0, 1, 2, 192>>
{0, 4}
<<0, 1, 2, 192>>
is a heap binaryshould beis a subbinary32(the bit size) should be26, but since it's a heap binary, the bit count is lost from the literal<<0, 1, 2, 3 : 2>>(3 * 8 + 2)
init.llvm.mlir
module @init {
llvm.func @"erlang:binary_part/2"(!llvm.i64, !llvm.i64) -> !llvm.i64
llvm.func @__lumen_builtin_malloc(!llvm.i32, !llvm.i64) -> !llvm<"i8*">
llvm.func @"erlang:display/1"(!llvm.i64) -> !llvm.i64
llvm.func @__lumen_builtin_math.div(!llvm.i64, !llvm.i64) -> !llvm.i64
llvm.func @"erlang:bit_size/1"(!llvm.i64) -> !llvm.i64
llvm.func @__lumen_builtin_binary_finish(!llvm.i64) -> !llvm.i64
llvm.func @__lumen_builtin_binary_push_integer(!llvm.i64, !llvm.i64, !llvm.i64, !llvm.i8, !llvm.i1, !llvm.i32) -> !llvm<"%binary.pushed = type { i64, i1 }">
llvm.func @__lumen_builtin_binary_start() -> !llvm.i64
llvm.func @__lumen_builtin_yield()
llvm.mlir.global external local_exec @CURRENT_REDUCTION_COUNT() : !llvm.i32
llvm.func @lumen_eh_personality(...) -> !llvm.i32
llvm.func @"init:start/0"() -> !llvm.i64 attributes {personality = @lumen_eh_personality} {
%0 = llvm.mlir.constant(20 : i32) : !llvm.i32
%1 = llvm.mlir.addressof @CURRENT_REDUCTION_COUNT : !llvm<"i32*">
%2 = llvm.load %1 : !llvm<"i32*">
%3 = llvm.icmp "uge" %2, %0 : !llvm.i32
llvm.cond_br %3, ^bb1, ^bb2
^bb1: // pred: ^bb0
llvm.call @__lumen_builtin_yield() : () -> ()
llvm.br ^bb2
^bb2: // 2 preds: ^bb0, ^bb1
%4 = llvm.call @__lumen_builtin_binary_start() : () -> !llvm.i64
%5 = llvm.mlir.constant(140737488355328 : i64) : !llvm.i64
%6 = llvm.mlir.constant(140737488355336 : i64) : !llvm.i64
%7 = llvm.mlir.constant(1 : i8) : !llvm.i8
%8 = llvm.mlir.constant(false) : !llvm.i1
%9 = llvm.mlir.constant(0 : i32) : !llvm.i32
%10 = llvm.call @__lumen_builtin_binary_push_integer(%4, %5, %6, %7, %8, %9) : (!llvm.i64, !llvm.i64, !llvm.i64, !llvm.i8, !llvm.i1, !llvm.i32) -> !llvm<"%binary.pushed = type { i64, i1 }">
%11 = llvm.extractvalue %10[0] : !llvm<"%binary.pushed = type { i64, i1 }">
%12 = llvm.extractvalue %10[1] : !llvm<"%binary.pushed = type { i64, i1 }">
llvm.cond_br %12, ^bb3(%11 : !llvm.i64), ^bb4
^bb3(%13: !llvm.i64): // pred: ^bb2
%14 = llvm.mlir.constant(140737488355329 : i64) : !llvm.i64
%15 = llvm.call @__lumen_builtin_binary_push_integer(%13, %14, %6, %7, %8, %9) : (!llvm.i64, !llvm.i64, !llvm.i64, !llvm.i8, !llvm.i1, !llvm.i32) -> !llvm<"%binary.pushed = type { i64, i1 }">
%16 = llvm.extractvalue %15[0] : !llvm<"%binary.pushed = type { i64, i1 }">
%17 = llvm.extractvalue %15[1] : !llvm<"%binary.pushed = type { i64, i1 }">
llvm.cond_br %17, ^bb5(%16 : !llvm.i64), ^bb4
^bb4: // 4 preds: ^bb2, ^bb3, ^bb5, ^bb6
llvm.unreachable
^bb5(%18: !llvm.i64): // pred: ^bb3
%19 = llvm.mlir.constant(140737488355330 : i64) : !llvm.i64
%20 = llvm.call @__lumen_builtin_binary_push_integer(%18, %19, %6, %7, %8, %9) : (!llvm.i64, !llvm.i64, !llvm.i64, !llvm.i8, !llvm.i1, !llvm.i32) -> !llvm<"%binary.pushed = type { i64, i1 }">
%21 = llvm.extractvalue %20[0] : !llvm<"%binary.pushed = type { i64, i1 }">
%22 = llvm.extractvalue %20[1] : !llvm<"%binary.pushed = type { i64, i1 }">
llvm.cond_br %22, ^bb6(%21 : !llvm.i64), ^bb4
^bb6(%23: !llvm.i64): // pred: ^bb5
%24 = llvm.mlir.constant(140737488355331 : i64) : !llvm.i64
%25 = llvm.call @__lumen_builtin_binary_push_integer(%23, %24, %19, %7, %8, %9) : (!llvm.i64, !llvm.i64, !llvm.i64, !llvm.i8, !llvm.i1, !llvm.i32) -> !llvm<"%binary.pushed = type { i64, i1 }">
%26 = llvm.extractvalue %25[0] : !llvm<"%binary.pushed = type { i64, i1 }">
%27 = llvm.extractvalue %25[1] : !llvm<"%binary.pushed = type { i64, i1 }">
llvm.cond_br %27, ^bb7(%26 : !llvm.i64), ^bb4
^bb7(%28: !llvm.i64): // pred: ^bb6
%29 = llvm.call @__lumen_builtin_binary_finish(%28) : (!llvm.i64) -> !llvm.i64
%30 = llvm.mlir.addressof @CURRENT_REDUCTION_COUNT : !llvm<"i32*">
%31 = llvm.mlir.constant(1 : i32) : !llvm.i32
%32 = llvm.atomicrmw add %30, %31 monotonic : !llvm.i32
%33 = llvm.call @"erlang:bit_size/1"(%29) {tail} : (!llvm.i64) -> !llvm.i64
%34 = llvm.call @__lumen_builtin_math.div(%33, %6) : (!llvm.i64, !llvm.i64) -> !llvm.i64
%35 = llvm.mlir.addressof @CURRENT_REDUCTION_COUNT : !llvm<"i32*">
%36 = llvm.atomicrmw add %35, %31 monotonic : !llvm.i32
%37 = llvm.call @"erlang:bit_size/1"(%29) {tail} : (!llvm.i64) -> !llvm.i64
%38 = llvm.mlir.addressof @CURRENT_REDUCTION_COUNT : !llvm<"i32*">
%39 = llvm.atomicrmw add %38, %31 monotonic : !llvm.i32
%40 = llvm.call @"erlang:display/1"(%37) {tail} : (!llvm.i64) -> !llvm.i64
%41 = llvm.mlir.addressof @CURRENT_REDUCTION_COUNT : !llvm<"i32*">
%42 = llvm.atomicrmw add %41, %31 monotonic : !llvm.i32
%43 = llvm.call @"erlang:display/1"(%29) {tail} : (!llvm.i64) -> !llvm.i64
%44 = llvm.mlir.constant(2 : i64) : !llvm.i64
%45 = llvm.mlir.constant(12 : i32) : !llvm.i32
%46 = llvm.call @__lumen_builtin_malloc(%45, %44) : (!llvm.i32, !llvm.i64) -> !llvm<"i8*">
%47 = llvm.bitcast %46 : !llvm<"i8*"> to !llvm<"%"type 0x7fd043836d20"*">
%48 = llvm.getelementptr %47[%9, %9] : (!llvm<"%"type 0x7fd043836d20"*">, !llvm.i32, !llvm.i32) -> !llvm<"i64*">
%49 = llvm.mlir.constant(985162418487298 : i64) : !llvm.i64
llvm.store %49, %48 : !llvm<"i64*">
%50 = llvm.getelementptr %47[%9, %31] : (!llvm<"%"type 0x7fd043836d20"*">, !llvm.i32, !llvm.i32) -> !llvm<"i64*">
llvm.store %5, %50 : !llvm<"i64*">
%51 = llvm.mlir.constant(2 : i32) : !llvm.i32
%52 = llvm.getelementptr %47[%9, %51] : (!llvm<"%"type 0x7fd043836d20"*">, !llvm.i32, !llvm.i32) -> !llvm<"i64*">
llvm.store %34, %52 : !llvm<"i64*">
%53 = llvm.ptrtoint %47 : !llvm<"%"type 0x7fd043836d20"*"> to !llvm.i64
%54 = llvm.mlir.addressof @CURRENT_REDUCTION_COUNT : !llvm<"i32*">
%55 = llvm.atomicrmw add %54, %31 monotonic : !llvm.i32
%56 = llvm.call @"erlang:display/1"(%53) {tail} : (!llvm.i64) -> !llvm.i64
%57 = llvm.mlir.addressof @CURRENT_REDUCTION_COUNT : !llvm<"i32*">
%58 = llvm.atomicrmw add %57, %31 monotonic : !llvm.i32
%59 = llvm.call @"erlang:binary_part/2"(%29, %53) {tail} : (!llvm.i64, !llvm.i64) -> !llvm.i64
%60 = llvm.mlir.addressof @CURRENT_REDUCTION_COUNT : !llvm<"i32*">
%61 = llvm.atomicrmw add %60, %31 monotonic : !llvm.i32
%62 = llvm.call @"erlang:display/1"(%59) {tail} : (!llvm.i64) -> !llvm.i64
llvm.return %62 : !llvm.i64
}
}