-
Notifications
You must be signed in to change notification settings - Fork 44
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
BUG: parse result error #500
Comments
Hello, I'm not able to attempt to replicate the error on
|
I cannot run the tests using an
|
@azteca1998 did you try from the starknet in rust repo? I have a PR up normally to add the test to the SiR suite. |
I managed to get it working with your SiR PR after tweaking it a bit (mostly running makefile rules until it had the necessary files). I think that specific error may have been fixed indirectly by the other bug's fix. Right now it's failing with the following:
Could you confirm if that's the case? |
That was one of the error, the parse result error comes from the execution part so you need to run the transaction skipping the validation |
I see, I commented out the validation and now it just segfaults on a memcpy operation within the contract trying to read or write from/to a null pointer. Do you have the Cairo source for the |
Weird, maybe I was on another commit, can check tmr. Here is the execute https://github.com/kkrt-labs/kakarot-ssj/blob/main/crates/contracts/src/eoa.cairo |
I've been debugging for a few hours now and I've found the following:
I tried simplifying the program, but:
fn try_into_bytes(self: Span<felt252>) {
let mut i = 0;
let mut bytes: Array<u8> = Default::default();
loop {
if (i == self.len()) {
break ();
};
let v: Option<u8> = (*self[i]).try_into();
match v {
Option::Some(v) => { bytes.append(v); },
Option::None => { break (); }
}
i += 1;
};
}
fn main() {
let mut data = array![0, 1, 2, 3, 4, 5, 6, 7].span();
try_into_bytes(data);
} I'll include here the loop function's MLIR and LLVM IR. Of course I've also tried reading those IRs but I haven't been able to find anything strange there. Loop function's MLIR llvm.func @"simple::simple::try_into_bytes[expr29](f0)"(%arg0: i64, %arg1: i128, %arg2: i32, %arg3: !llvm.struct<(struct<(ptr, i32, i32, i32)>)>, %arg4: !llvm.struct<(ptr, i32, i32, i32)>) -> !llvm.struct<(i64, i128, struct<(i64, array<24 x i8>)>)> attributes {llvm.emit_c_interface, sym_visibility = "public"} {
%0 = llvm.mlir.constant(256 : i64) : i64
%1 = llvm.mlir.constant(375233589013918064796019 : i252) : i252
%2 = llvm.mlir.constant(true) : i1
%3 = llvm.mlir.constant(1 : i64) : i64
%4 = llvm.mlir.constant(1024 : i32) : i32
%5 = llvm.mlir.constant(8 : i32) : i32
%6 = llvm.mlir.constant(0 : i32) : i32
%7 = llvm.mlir.constant(1 : i32) : i32
%8 = llvm.mlir.constant(false) : i1
%9 = llvm.mlir.constant(9120 : i128) : i128
%10 = llvm.mlir.constant(0 : i64) : i64
%11 = llvm.mlir.constant(1 : index) : i64
%12 = llvm.alloca %11 x i64 : (i64) -> !llvm.ptr
llvm.store %10, %12 : i64, !llvm.ptr
%13 = llvm.alloca %3 x !llvm.struct<(i64, array<24 x i8>)> {alignment = 8 : i64} : (i64) -> !llvm.ptr
%14 = llvm.alloca %3 x !llvm.struct<(i64, array<24 x i8>)> {alignment = 8 : i64} : (i64) -> !llvm.ptr
%15 = llvm.alloca %3 x !llvm.struct<(i64, array<20 x i8>)> {alignment = 8 : i64} : (i64) -> !llvm.ptr
%16 = llvm.alloca %3 x !llvm.struct<(i64, array<24 x i8>)> {alignment = 8 : i64} : (i64) -> !llvm.ptr
%17 = llvm.alloca %3 x !llvm.struct<(i8, array<1 x i8>)> {alignment = 1 : i64} : (i64) -> !llvm.ptr
%18 = llvm.alloca %3 x !llvm.struct<(i64, array<24 x i8>)> {alignment = 8 : i64} : (i64) -> !llvm.ptr
%19 = llvm.alloca %3 x !llvm.struct<(i64, array<20 x i8>)> {alignment = 8 : i64} : (i64) -> !llvm.ptr
%20 = llvm.alloca %3 x !llvm.struct<(i64, array<24 x i8>)> {alignment = 8 : i64} : (i64) -> !llvm.ptr
llvm.br ^bb1(%arg0, %arg1, %arg2, %arg3, %arg4 : i64, i128, i32, !llvm.struct<(struct<(ptr, i32, i32, i32)>)>, !llvm.struct<(ptr, i32, i32, i32)>)
^bb1(%21: i64, %22: i128, %23: i32, %24: !llvm.struct<(struct<(ptr, i32, i32, i32)>)>, %25: !llvm.struct<(ptr, i32, i32, i32)>): // 2 preds: ^bb0, ^bb14
%26 = llvm.add %21, %3 : i64
%27 = llvm.icmp "uge" %22, %9 : i128
%28 = llvm.call_intrinsic "llvm.usub.sat"(%22, %9) : (i128, i128) -> i128 {intrin = "llvm.usub.sat"}
llvm.cond_br %27, ^bb2(%24 : !llvm.struct<(struct<(ptr, i32, i32, i32)>)>), ^bb15(%25 : !llvm.struct<(ptr, i32, i32, i32)>)
^bb2(%29: !llvm.struct<(struct<(ptr, i32, i32, i32)>)>): // pred: ^bb1
%30 = llvm.extractvalue %29[0] : !llvm.struct<(struct<(ptr, i32, i32, i32)>)>
%31 = llvm.extractvalue %30[1] : !llvm.struct<(ptr, i32, i32, i32)>
%32 = llvm.extractvalue %30[2] : !llvm.struct<(ptr, i32, i32, i32)>
%33 = llvm.sub %32, %31 : i32
%34 = llvm.icmp "eq" %23, %33 : i32
llvm.cond_br %34, ^bb9(%14, %14, %26 : !llvm.ptr, !llvm.ptr, i64), ^bb3(%29 : !llvm.struct<(struct<(ptr, i32, i32, i32)>)>)
^bb3(%35: !llvm.struct<(struct<(ptr, i32, i32, i32)>)>): // pred: ^bb2
%36 = llvm.extractvalue %35[0] : !llvm.struct<(struct<(ptr, i32, i32, i32)>)>
%37 = llvm.call @"core::array::array_at::<core::felt252>(f6)"(%26, %36, %23) : (i64, !llvm.struct<(ptr, i32, i32, i32)>, i32) -> !llvm.struct<(i64, struct<(i64, array<20 x i8>)>)>
%38 = llvm.extractvalue %37[0] : !llvm.struct<(i64, struct<(i64, array<20 x i8>)>)>
%39 = llvm.extractvalue %37[1] : !llvm.struct<(i64, struct<(i64, array<20 x i8>)>)>
llvm.store %39, %15 {alignment = 8 : i64} : !llvm.struct<(i64, array<20 x i8>)>, !llvm.ptr
%40 = llvm.load %15 {alignment = 8 : i64} : !llvm.ptr -> i1
llvm.switch %40 : i1, ^bb4 [
0: ^bb6,
1: ^bb7(%15, %25, %16, %16, %38 : !llvm.ptr, !llvm.struct<(ptr, i32, i32, i32)>, !llvm.ptr, !llvm.ptr, i64)
]
^bb4: // 3 preds: ^bb3, ^bb6, ^bb13
llvm.cond_br %8, ^bb5, ^bb16
^bb5: // pred: ^bb4
llvm.unreachable
^bb6: // pred: ^bb3
%41 = llvm.load %15 {alignment = 8 : i64} : !llvm.ptr -> !llvm.struct<(i1, struct<(ptr)>)>
%42 = llvm.extractvalue %41[1] : !llvm.struct<(i1, struct<(ptr)>)>
%43 = llvm.extractvalue %42[0] : !llvm.struct<(ptr)>
%44 = llvm.load %43 {alignment = 8 : i64} : !llvm.ptr -> i252
llvm.call @free(%43) : (!llvm.ptr) -> ()
%45 = llvm.call @"core::integer::Felt252TryIntoU8::try_into(f5)"(%38, %44) : (i64, i252) -> !llvm.struct<(i64, struct<(i8, array<1 x i8>)>)>
%46 = llvm.extractvalue %45[0] : !llvm.struct<(i64, struct<(i8, array<1 x i8>)>)>
%47 = llvm.extractvalue %45[1] : !llvm.struct<(i64, struct<(i8, array<1 x i8>)>)>
llvm.store %47, %17 {alignment = 1 : i64} : !llvm.struct<(i8, array<1 x i8>)>, !llvm.ptr
%48 = llvm.load %17 {alignment = 1 : i64} : !llvm.ptr -> i1
llvm.switch %48 : i1, ^bb4 [
0: ^bb8,
1: ^bb9(%18, %18, %46 : !llvm.ptr, !llvm.ptr, i64)
]
^bb7(%49: !llvm.ptr, %50: !llvm.struct<(ptr, i32, i32, i32)>, %51: !llvm.ptr, %52: !llvm.ptr, %53: i64): // 2 preds: ^bb3, ^bb13
%54 = llvm.load %49 {alignment = 8 : i64} : !llvm.ptr -> !llvm.struct<(i1, struct<(struct<()>, struct<(ptr, i32, i32, i32)>)>)>
%55 = llvm.extractvalue %54[1] : !llvm.struct<(i1, struct<(struct<()>, struct<(ptr, i32, i32, i32)>)>)>
%56 = llvm.extractvalue %50[0] : !llvm.struct<(ptr, i32, i32, i32)>
llvm.call @free(%56) : (!llvm.ptr) -> ()
%57 = llvm.mlir.undef : !llvm.struct<(i1, struct<(struct<()>, struct<(ptr, i32, i32, i32)>)>)>
%58 = llvm.insertvalue %2, %57[0] : !llvm.struct<(i1, struct<(struct<()>, struct<(ptr, i32, i32, i32)>)>)>
%59 = llvm.insertvalue %55, %58[1] : !llvm.struct<(i1, struct<(struct<()>, struct<(ptr, i32, i32, i32)>)>)>
llvm.store %59, %51 {alignment = 8 : i64} : !llvm.struct<(i1, struct<(struct<()>, struct<(ptr, i32, i32, i32)>)>)>, !llvm.ptr
%60 = llvm.load %52 {alignment = 8 : i64} : !llvm.ptr -> !llvm.struct<(i64, array<24 x i8>)>
%61 = llvm.mlir.undef : !llvm.struct<(i64, i128, struct<(i64, array<24 x i8>)>)>
%62 = llvm.insertvalue %53, %61[0] : !llvm.struct<(i64, i128, struct<(i64, array<24 x i8>)>)>
%63 = llvm.insertvalue %28, %62[1] : !llvm.struct<(i64, i128, struct<(i64, array<24 x i8>)>)>
%64 = llvm.insertvalue %60, %63[2] : !llvm.struct<(i64, i128, struct<(i64, array<24 x i8>)>)>
llvm.return %64 : !llvm.struct<(i64, i128, struct<(i64, array<24 x i8>)>)>
^bb8: // pred: ^bb6
%65 = llvm.load %17 {alignment = 1 : i64} : !llvm.ptr -> !llvm.struct<(i1, i8)>
%66 = llvm.extractvalue %65[1] : !llvm.struct<(i1, i8)>
%67 = llvm.extractvalue %25[2] : !llvm.struct<(ptr, i32, i32, i32)>
%68 = llvm.extractvalue %25[3] : !llvm.struct<(ptr, i32, i32, i32)>
%69 = llvm.icmp "ult" %67, %68 : i32
llvm.cond_br %69, ^bb13(%25 : !llvm.struct<(ptr, i32, i32, i32)>), ^bb10
^bb9(%70: !llvm.ptr, %71: !llvm.ptr, %72: i64): // 2 preds: ^bb2, ^bb6
%73 = llvm.mlir.undef : !llvm.struct<()>
%74 = llvm.mlir.undef : !llvm.struct<(struct<(ptr, i32, i32, i32)>, i32, struct<()>)>
%75 = llvm.insertvalue %25, %74[0] : !llvm.struct<(struct<(ptr, i32, i32, i32)>, i32, struct<()>)>
%76 = llvm.insertvalue %23, %75[1] : !llvm.struct<(struct<(ptr, i32, i32, i32)>, i32, struct<()>)>
%77 = llvm.insertvalue %73, %76[2] : !llvm.struct<(struct<(ptr, i32, i32, i32)>, i32, struct<()>)>
%78 = llvm.mlir.undef : !llvm.struct<(i1, struct<(struct<(ptr, i32, i32, i32)>, i32, struct<()>)>)>
%79 = llvm.insertvalue %8, %78[0] : !llvm.struct<(i1, struct<(struct<(ptr, i32, i32, i32)>, i32, struct<()>)>)>
%80 = llvm.insertvalue %77, %79[1] : !llvm.struct<(i1, struct<(struct<(ptr, i32, i32, i32)>, i32, struct<()>)>)>
llvm.store %80, %70 {alignment = 8 : i64} : !llvm.struct<(i1, struct<(struct<(ptr, i32, i32, i32)>, i32, struct<()>)>)>, !llvm.ptr
%81 = llvm.load %71 {alignment = 8 : i64} : !llvm.ptr -> !llvm.struct<(i64, array<24 x i8>)>
%82 = llvm.mlir.undef : !llvm.struct<(i64, i128, struct<(i64, array<24 x i8>)>)>
%83 = llvm.insertvalue %72, %82[0] : !llvm.struct<(i64, i128, struct<(i64, array<24 x i8>)>)>
%84 = llvm.insertvalue %28, %83[1] : !llvm.struct<(i64, i128, struct<(i64, array<24 x i8>)>)>
%85 = llvm.insertvalue %81, %84[2] : !llvm.struct<(i64, i128, struct<(i64, array<24 x i8>)>)>
llvm.return %85 : !llvm.struct<(i64, i128, struct<(i64, array<24 x i8>)>)>
^bb10: // pred: ^bb8
%86 = llvm.extractvalue %25[1] : !llvm.struct<(ptr, i32, i32, i32)>
%87 = llvm.icmp "ne" %86, %6 : i32
llvm.cond_br %87, ^bb11, ^bb12
^bb11: // pred: ^bb10
%88 = llvm.extractvalue %25[1] : !llvm.struct<(ptr, i32, i32, i32)>
%89 = llvm.zext %88 : i32 to i64
%90 = llvm.extractvalue %25[0] : !llvm.struct<(ptr, i32, i32, i32)>
%91 = llvm.getelementptr %90[%89] : (!llvm.ptr, i64) -> !llvm.ptr, i8
%92 = llvm.sub %67, %88 : i32
%93 = llvm.zext %92 : i32 to i64
llvm.call_intrinsic "llvm.memmove"(%90, %91, %93, %8) : (!llvm.ptr, !llvm.ptr, i64, i1) -> () {intrin = "llvm.memmove"}
%94 = llvm.insertvalue %6, %25[1] : !llvm.struct<(ptr, i32, i32, i32)>
%95 = llvm.insertvalue %92, %94[2] : !llvm.struct<(ptr, i32, i32, i32)>
llvm.br ^bb13(%95 : !llvm.struct<(ptr, i32, i32, i32)>)
^bb12: // pred: ^bb10
%96 = llvm.shl %67, %7 : i32
%97 = llvm.intr.umin(%96, %4) : (i32, i32) -> i32
%98 = llvm.add %97, %67 : i32
%99 = llvm.intr.umax(%98, %5) : (i32, i32) -> i32
%100 = llvm.zext %99 : i32 to i64
%101 = llvm.extractvalue %25[0] : !llvm.struct<(ptr, i32, i32, i32)>
%102 = llvm.call @realloc(%101, %100) : (!llvm.ptr, i64) -> !llvm.ptr
%103 = llvm.insertvalue %102, %25[0] : !llvm.struct<(ptr, i32, i32, i32)>
%104 = llvm.insertvalue %99, %103[3] : !llvm.struct<(ptr, i32, i32, i32)>
llvm.br ^bb13(%104 : !llvm.struct<(ptr, i32, i32, i32)>)
^bb13(%105: !llvm.struct<(ptr, i32, i32, i32)>): // 3 preds: ^bb8, ^bb11, ^bb12
%106 = llvm.extractvalue %105[0] : !llvm.struct<(ptr, i32, i32, i32)>
%107 = llvm.extractvalue %105[2] : !llvm.struct<(ptr, i32, i32, i32)>
%108 = llvm.zext %107 : i32 to i64
%109 = llvm.getelementptr %106[%108] : (!llvm.ptr, i64) -> !llvm.ptr, i8
llvm.store %66, %109 {alignment = 1 : i64} : i8, !llvm.ptr
%110 = llvm.add %107, %7 : i32
%111 = llvm.insertvalue %110, %105[2] : !llvm.struct<(ptr, i32, i32, i32)>
%112 = llvm.call @"core::integer::U32Add::add(f3)"(%46, %23, %7) : (i64, i32, i32) -> !llvm.struct<(i64, struct<(i64, array<20 x i8>)>)>
%113 = llvm.extractvalue %112[0] : !llvm.struct<(i64, struct<(i64, array<20 x i8>)>)>
%114 = llvm.extractvalue %112[1] : !llvm.struct<(i64, struct<(i64, array<20 x i8>)>)>
llvm.store %114, %19 {alignment = 8 : i64} : !llvm.struct<(i64, array<20 x i8>)>, !llvm.ptr
%115 = llvm.load %19 {alignment = 8 : i64} : !llvm.ptr -> i1
llvm.switch %115 : i1, ^bb4 [
0: ^bb14,
1: ^bb7(%19, %105, %20, %20, %113 : !llvm.ptr, !llvm.struct<(ptr, i32, i32, i32)>, !llvm.ptr, !llvm.ptr, i64)
]
^bb14: // pred: ^bb13
%116 = llvm.load %19 {alignment = 8 : i64} : !llvm.ptr -> !llvm.struct<(i1, struct<(i32)>)>
%117 = llvm.extractvalue %116[1] : !llvm.struct<(i1, struct<(i32)>)>
%118 = llvm.extractvalue %117[0] : !llvm.struct<(i32)>
%119 = llvm.load %12 : !llvm.ptr -> i64
%120 = llvm.add %119, %3 : i64
llvm.store %120, %12 : i64, !llvm.ptr
llvm.br ^bb1(%113, %28, %118, %35, %111 : i64, i128, i32, !llvm.struct<(struct<(ptr, i32, i32, i32)>)>, !llvm.struct<(ptr, i32, i32, i32)>)
^bb15(%121: !llvm.struct<(ptr, i32, i32, i32)>): // pred: ^bb1
%122 = llvm.extractvalue %121[0] : !llvm.struct<(ptr, i32, i32, i32)>
llvm.call @free(%122) : (!llvm.ptr) -> ()
%123 = llvm.mlir.null : !llvm.ptr
%124 = llvm.mlir.undef : !llvm.struct<(ptr, i32, i32, i32)>
%125 = llvm.insertvalue %123, %124[0] : !llvm.struct<(ptr, i32, i32, i32)>
%126 = llvm.insertvalue %6, %125[1] : !llvm.struct<(ptr, i32, i32, i32)>
%127 = llvm.insertvalue %6, %126[2] : !llvm.struct<(ptr, i32, i32, i32)>
%128 = llvm.insertvalue %6, %127[3] : !llvm.struct<(ptr, i32, i32, i32)>
%129 = llvm.call @realloc(%123, %0) : (!llvm.ptr, i64) -> !llvm.ptr
%130 = llvm.insertvalue %129, %128[0] : !llvm.struct<(ptr, i32, i32, i32)>
%131 = llvm.insertvalue %5, %130[3] : !llvm.struct<(ptr, i32, i32, i32)>
llvm.store %1, %129 {alignment = 8 : i64} : i252, !llvm.ptr
%132 = llvm.insertvalue %7, %131[2] : !llvm.struct<(ptr, i32, i32, i32)>
%133 = llvm.mlir.undef : !llvm.struct<()>
%134 = llvm.mlir.undef : !llvm.struct<(struct<()>, struct<(ptr, i32, i32, i32)>)>
%135 = llvm.insertvalue %133, %134[0] : !llvm.struct<(struct<()>, struct<(ptr, i32, i32, i32)>)>
%136 = llvm.insertvalue %132, %135[1] : !llvm.struct<(struct<()>, struct<(ptr, i32, i32, i32)>)>
%137 = llvm.mlir.undef : !llvm.struct<(i1, struct<(struct<()>, struct<(ptr, i32, i32, i32)>)>)>
%138 = llvm.insertvalue %2, %137[0] : !llvm.struct<(i1, struct<(struct<()>, struct<(ptr, i32, i32, i32)>)>)>
%139 = llvm.insertvalue %136, %138[1] : !llvm.struct<(i1, struct<(struct<()>, struct<(ptr, i32, i32, i32)>)>)>
llvm.store %139, %13 {alignment = 8 : i64} : !llvm.struct<(i1, struct<(struct<()>, struct<(ptr, i32, i32, i32)>)>)>, !llvm.ptr
%140 = llvm.load %13 {alignment = 8 : i64} : !llvm.ptr -> !llvm.struct<(i64, array<24 x i8>)>
%141 = llvm.mlir.undef : !llvm.struct<(i64, i128, struct<(i64, array<24 x i8>)>)>
%142 = llvm.insertvalue %26, %141[0] : !llvm.struct<(i64, i128, struct<(i64, array<24 x i8>)>)>
%143 = llvm.insertvalue %28, %142[1] : !llvm.struct<(i64, i128, struct<(i64, array<24 x i8>)>)>
%144 = llvm.insertvalue %140, %143[2] : !llvm.struct<(i64, i128, struct<(i64, array<24 x i8>)>)>
llvm.return %144 : !llvm.struct<(i64, i128, struct<(i64, array<24 x i8>)>)>
^bb16: // pred: ^bb4
%145 = llvm.mlir.addressof @assert_msg_1 : !llvm.ptr
llvm.call @puts(%145) : (!llvm.ptr) -> ()
llvm.call @abort() : () -> ()
llvm.unreachable
} Loop function's LLVM IRdefine { i64, i128, { i64, [24 x i8] } } @"simple::simple::try_into_bytes[expr29](f0)"(i64 %0, i128 %1, i32 %2, { { ptr, i32, i32, i32 } } %3, { ptr, i32, i32, i32 } %4) {
%6 = alloca i64, i64 1, align 8
store i64 0, ptr %6, align 8
%7 = alloca { i64, [24 x i8] }, i64 1, align 8
%8 = alloca { i64, [24 x i8] }, i64 1, align 8
%9 = alloca { i64, [20 x i8] }, i64 1, align 8
%10 = alloca { i64, [24 x i8] }, i64 1, align 8
%11 = alloca { i8, [1 x i8] }, i64 1, align 1
%12 = alloca { i64, [24 x i8] }, i64 1, align 8
%13 = alloca { i64, [20 x i8] }, i64 1, align 8
%14 = alloca { i64, [24 x i8] }, i64 1, align 8
br label %15
15: ; preds = %115, %5
%16 = phi i64 [ %112, %115 ], [ %0, %5 ]
%17 = phi i128 [ %23, %115 ], [ %1, %5 ]
%18 = phi i32 [ %118, %115 ], [ %2, %5 ]
%19 = phi { { ptr, i32, i32, i32 } } [ %32, %115 ], [ %3, %5 ]
%20 = phi { ptr, i32, i32, i32 } [ %110, %115 ], [ %4, %5 ]
%21 = add i64 %16, 1
%22 = icmp uge i128 %17, 9120
%23 = call i128 @llvm.usub.sat.i128(i128 %17, i128 9120)
br i1 %22, label %24, label %121
24: ; preds = %15
%25 = phi { { ptr, i32, i32, i32 } } [ %19, %15 ]
%26 = extractvalue { { ptr, i32, i32, i32 } } %25, 0
%27 = extractvalue { ptr, i32, i32, i32 } %26, 1
%28 = extractvalue { ptr, i32, i32, i32 } %26, 2
%29 = sub i32 %28, %27
%30 = icmp eq i32 %18, %29
br i1 %30, label %69, label %31
31: ; preds = %24
%32 = phi { { ptr, i32, i32, i32 } } [ %25, %24 ]
%33 = extractvalue { { ptr, i32, i32, i32 } } %32, 0
%34 = call { i64, { i64, [20 x i8] } } @"core::array::array_at::<core::felt252>(f6)"(i64 %21, { ptr, i32, i32, i32 } %33, i32 %18)
%35 = extractvalue { i64, { i64, [20 x i8] } } %34, 0
%36 = extractvalue { i64, { i64, [20 x i8] } } %34, 1
store { i64, [20 x i8] } %36, ptr %9, align 8
%37 = load i1, ptr %9, align 8
switch i1 %37, label %38 [
i1 false, label %40
i1 true, label %49
]
38: ; preds = %103, %40, %31
br i1 false, label %39, label %134
39: ; preds = %38
unreachable
40: ; preds = %31
%41 = load { i1, { ptr } }, ptr %9, align 8
%42 = extractvalue { i1, { ptr } } %41, 1
%43 = extractvalue { ptr } %42, 0
%44 = load i252, ptr %43, align 8
call void @free(ptr %43)
%45 = call { i64, { i8, [1 x i8] } } @"core::integer::Felt252TryIntoU8::try_into(f5)"(i64 %35, i252 %44)
%46 = extractvalue { i64, { i8, [1 x i8] } } %45, 0
%47 = extractvalue { i64, { i8, [1 x i8] } } %45, 1
store { i8, [1 x i8] } %47, ptr %11, align 1
%48 = load i1, ptr %11, align 1
switch i1 %48, label %38 [
i1 false, label %63
i1 true, label %69
]
49: ; preds = %103, %31
%50 = phi ptr [ %13, %103 ], [ %9, %31 ]
%51 = phi { ptr, i32, i32, i32 } [ %104, %103 ], [ %20, %31 ]
%52 = phi ptr [ %14, %103 ], [ %10, %31 ]
%53 = phi ptr [ %14, %103 ], [ %10, %31 ]
%54 = phi i64 [ %112, %103 ], [ %35, %31 ]
%55 = load { i1, { {}, { ptr, i32, i32, i32 } } }, ptr %50, align 8
%56 = extractvalue { i1, { {}, { ptr, i32, i32, i32 } } } %55, 1
%57 = extractvalue { ptr, i32, i32, i32 } %51, 0
call void @free(ptr %57)
%58 = insertvalue { i1, { {}, { ptr, i32, i32, i32 } } } { i1 true, { {}, { ptr, i32, i32, i32 } } undef }, { {}, { ptr, i32, i32, i32 } } %56, 1
store { i1, { {}, { ptr, i32, i32, i32 } } } %58, ptr %52, align 8
%59 = load { i64, [24 x i8] }, ptr %53, align 8
%60 = insertvalue { i64, i128, { i64, [24 x i8] } } undef, i64 %54, 0
%61 = insertvalue { i64, i128, { i64, [24 x i8] } } %60, i128 %23, 1
%62 = insertvalue { i64, i128, { i64, [24 x i8] } } %61, { i64, [24 x i8] } %59, 2
ret { i64, i128, { i64, [24 x i8] } } %62
63: ; preds = %40
%64 = load { i1, i8 }, ptr %11, align 1
%65 = extractvalue { i1, i8 } %64, 1
%66 = extractvalue { ptr, i32, i32, i32 } %20, 2
%67 = extractvalue { ptr, i32, i32, i32 } %20, 3
%68 = icmp ult i32 %66, %67
br i1 %68, label %103, label %81
69: ; preds = %40, %24
%70 = phi ptr [ %12, %40 ], [ %8, %24 ]
%71 = phi ptr [ %12, %40 ], [ %8, %24 ]
%72 = phi i64 [ %46, %40 ], [ %21, %24 ]
%73 = insertvalue { { ptr, i32, i32, i32 }, i32, {} } undef, { ptr, i32, i32, i32 } %20, 0
%74 = insertvalue { { ptr, i32, i32, i32 }, i32, {} } %73, i32 %18, 1
%75 = insertvalue { { ptr, i32, i32, i32 }, i32, {} } %74, {} undef, 2
%76 = insertvalue { i1, { { ptr, i32, i32, i32 }, i32, {} } } { i1 false, { { ptr, i32, i32, i32 }, i32, {} } undef }, { { ptr, i32, i32, i32 }, i32, {} } %75, 1
store { i1, { { ptr, i32, i32, i32 }, i32, {} } } %76, ptr %70, align 8
%77 = load { i64, [24 x i8] }, ptr %71, align 8
%78 = insertvalue { i64, i128, { i64, [24 x i8] } } undef, i64 %72, 0
%79 = insertvalue { i64, i128, { i64, [24 x i8] } } %78, i128 %23, 1
%80 = insertvalue { i64, i128, { i64, [24 x i8] } } %79, { i64, [24 x i8] } %77, 2
ret { i64, i128, { i64, [24 x i8] } } %80
81: ; preds = %63
%82 = extractvalue { ptr, i32, i32, i32 } %20, 1
%83 = icmp ne i32 %82, 0
br i1 %83, label %84, label %93
84: ; preds = %81
%85 = extractvalue { ptr, i32, i32, i32 } %20, 1
%86 = zext i32 %85 to i64
%87 = extractvalue { ptr, i32, i32, i32 } %20, 0
%88 = getelementptr i8, ptr %87, i64 %86
%89 = sub i32 %66, %85
%90 = zext i32 %89 to i64
call void @llvm.memmove.p0.p0.i64(ptr %87, ptr %88, i64 %90, i1 false)
%91 = insertvalue { ptr, i32, i32, i32 } %20, i32 0, 1
%92 = insertvalue { ptr, i32, i32, i32 } %91, i32 %89, 2
br label %103
93: ; preds = %81
%94 = shl i32 %66, 1
%95 = call i32 @llvm.umin.i32(i32 %94, i32 1024)
%96 = add i32 %95, %66
%97 = call i32 @llvm.umax.i32(i32 %96, i32 8)
%98 = zext i32 %97 to i64
%99 = extractvalue { ptr, i32, i32, i32 } %20, 0
%100 = call ptr @realloc(ptr %99, i64 %98)
%101 = insertvalue { ptr, i32, i32, i32 } %20, ptr %100, 0
%102 = insertvalue { ptr, i32, i32, i32 } %101, i32 %97, 3
br label %103
103: ; preds = %84, %93, %63
%104 = phi { ptr, i32, i32, i32 } [ %102, %93 ], [ %92, %84 ], [ %20, %63 ]
%105 = extractvalue { ptr, i32, i32, i32 } %104, 0
%106 = extractvalue { ptr, i32, i32, i32 } %104, 2
%107 = zext i32 %106 to i64
%108 = getelementptr i8, ptr %105, i64 %107
store i8 %65, ptr %108, align 1
%109 = add i32 %106, 1
%110 = insertvalue { ptr, i32, i32, i32 } %104, i32 %109, 2
%111 = call { i64, { i64, [20 x i8] } } @"core::integer::U32Add::add(f3)"(i64 %46, i32 %18, i32 1)
%112 = extractvalue { i64, { i64, [20 x i8] } } %111, 0
%113 = extractvalue { i64, { i64, [20 x i8] } } %111, 1
store { i64, [20 x i8] } %113, ptr %13, align 8
%114 = load i1, ptr %13, align 8
switch i1 %114, label %38 [
i1 false, label %115
i1 true, label %49
]
115: ; preds = %103
%116 = load { i1, { i32 } }, ptr %13, align 8
%117 = extractvalue { i1, { i32 } } %116, 1
%118 = extractvalue { i32 } %117, 0
%119 = load i64, ptr %6, align 8
%120 = add i64 %119, 1
store i64 %120, ptr %6, align 8
br label %15
121: ; preds = %15
%122 = phi { ptr, i32, i32, i32 } [ %20, %15 ]
%123 = extractvalue { ptr, i32, i32, i32 } %122, 0
call void @free(ptr %123)
%124 = call ptr @realloc(ptr null, i64 256)
%125 = insertvalue { ptr, i32, i32, i32 } zeroinitializer, ptr %124, 0
%126 = insertvalue { ptr, i32, i32, i32 } %125, i32 8, 3
store i252 375233589013918064796019, ptr %124, align 8
%127 = insertvalue { ptr, i32, i32, i32 } %126, i32 1, 2
%128 = insertvalue { {}, { ptr, i32, i32, i32 } } undef, { ptr, i32, i32, i32 } %127, 1
%129 = insertvalue { i1, { {}, { ptr, i32, i32, i32 } } } { i1 true, { {}, { ptr, i32, i32, i32 } } undef }, { {}, { ptr, i32, i32, i32 } } %128, 1
store { i1, { {}, { ptr, i32, i32, i32 } } } %129, ptr %7, align 8
%130 = load { i64, [24 x i8] }, ptr %7, align 8
%131 = insertvalue { i64, i128, { i64, [24 x i8] } } undef, i64 %21, 0
%132 = insertvalue { i64, i128, { i64, [24 x i8] } } %131, i128 %23, 1
%133 = insertvalue { i64, i128, { i64, [24 x i8] } } %132, { i64, [24 x i8] } %130, 2
ret { i64, i128, { i64, [24 x i8] } } %133
134: ; preds = %38
call void @puts(ptr @assert_msg_1)
call void @abort()
unreachable
} |
@azteca1998 just checking but you are getting this on the unwinding right: thread 'integration_tests::complex_contracts::kakarot::test_kakarot_contract' panicked at /Users/greg/.cargo/git/checkouts/cairo_native-0bad8506281b7281/4cd14b1/src/values.rs:531:21:
assertion failed: length_value >= offset_value
stack backtrace:
0: rust_begin_unwind
at /rustc/82e1608dfa6e0b5569232559e3d385fea5a93112/library/std/src/panicking.rs:645:5
1: core::panicking::panic_fmt
at /rustc/82e1608dfa6e0b5569232559e3d385fea5a93112/library/core/src/panicking.rs:72:14
2: core::panicking::panic
at /rustc/82e1608dfa6e0b5569232559e3d385fea5a93112/library/core/src/panicking.rs:127:5
3: cairo_native::values::JitValue::from_jit
at /Users/greg/.cargo/git/checkouts/cairo_native-0bad8506281b7281/4cd14b1/src/values.rs:531:21
4: cairo_native::values::JitValue::from_jit
at /Users/greg/.cargo/git/checkouts/cairo_native-0bad8506281b7281/4cd14b1/src/values.rs:657:38
5: cairo_native::executor::parse_result
at /Users/greg/.cargo/git/checkouts/cairo_native-0bad8506281b7281/4cd14b1/src/executor.rs:731:37
6: cairo_native::executor::invoke_dynamic
at /Users/greg/.cargo/git/checkouts/cairo_native-0bad8506281b7281/4cd14b1/src/executor.rs:292:24
7: cairo_native::executor::jit::JitNativeExecutor::invoke_contract_dynamic
at /Users/greg/.cargo/git/checkouts/cairo_native-0bad8506281b7281/4cd14b1/src/executor/jit.rs:125:56
8: starknet_in_rust::execution::execution_entry_point::ExecutionEntryPoint::native_execute
at ./src/execution/execution_entry_point.rs:773:46
9: starknet_in_rust::execution::execution_entry_point::ExecutionEntryPoint::execute
at ./src/execution/execution_entry_point.rs:168:23
10: starknet_in_rust::transaction::invoke_function::InvokeFunction::run_validate_entrypoint
at ./src/transaction/invoke_function.rs:273:49
11: starknet_in_rust::transaction::invoke_function::InvokeFunction::apply
at ./src/transaction/invoke_function.rs:366:13
12: starknet_in_rust::transaction::invoke_function::InvokeFunction::execute::{{closure}}
at ./src/transaction/invoke_function.rs:461:28
13: starknet_in_rust::transaction::invoke_function::InvokeFunction::execute
at ./src/transaction/invoke_function.rs:425:5
14: starknet_in_rust::transaction::Transaction::execute
at ./src/transaction/mod.rs:224:48
15: tests::integration_tests::cairo_native::TestState::execute_transaction
at ./tests/integration_tests/cairo_native.rs:1074:39
16: tests::integration_tests::complex_contracts::kakarot::test_kakarot_contract
at ./tests/integration_tests/complex_contracts/kakarot/mod.rs:299:28
17: tests::integration_tests::complex_contracts::kakarot::test_kakarot_contract::{{closure}}
at ./tests/integration_tests/complex_contracts/kakarot/mod.rs:22:27
18: core::ops::function::FnOnce::call_once
at /rustc/82e1608dfa6e0b5569232559e3d385fea5a93112/library/core/src/ops/function.rs:250:5
19: core::ops::function::FnOnce::call_once
at /rustc/82e1608dfa6e0b5569232559e3d385fea5a93112/library/core/src/ops/function.rs:250:5
libunwind: malformed __unwind_info at 0x18370BCA8 bad second level page
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace. If I can help in anyway for debugging let me know. I also bumped native to the latest commit and the validate issue ( |
Just in case, can you try to update to the latest native commit? |
Bumped to 60ed062 but still getting the same error |
This is more a comment to keep track of the information I've been finding. On x86_64, the program from @azteca1998 segfaults, but on a Mac m1 it doesn't. My guess is that there are some assumptions here where in x86 it's more strict and on arm it isn't, but at the end the result is wrong nevertheless. My guess is this is related to enum handling, probably panic related ones. fn try_into_bytes(self: Span<felt252>) {
let mut i = 0;
let mut bytes: Array<u8> = Default::default();
loop {
// adding a print here makes it not segfault on x86
if (i == self.len()) {
break ();
};
let v: Option<u8> = (*self[i]).try_into();
match v {
Option::Some(v) => { bytes.append(v); },
Option::None => { break (); }
}
i += 1;
};
}
fn main() {
let mut data = array![0, 1, 2, 3, 4, 5, 6, 7].span();
try_into_bytes(data);
} I could find a more minimal program: fn try_into_bytes(self: Span<felt252>) {
let mut i = 0;
let mut bytes: Array<u8> = Default::default();
loop {
// removing self.len() to a 1 makes it not segfault in x86
if (i == self.len()) {
break ();
};
let v: Option<u8> = Option::None;
match v {
Option::Some(v) => {
bytes.append(v);
},
Option::None => {
break ();
}
}
i += 1;
};
}
fn main() {
let mut data = array![].span();
try_into_bytes(data);
} With this we can rule out anything to do with the try_into. Here is the x86 assembly of the first program with some comments: Dump of assembler code for function program::program::try_into_bytes(f1):
0x00007ffff7fbf000 <+0>: push r14
0x00007ffff7fbf002 <+2>: push rbx ; here rbx has an addressable address
0x00007ffff7fbf003 <+3>: sub rsp,0x98
0x00007ffff7fbf00a <+10>: mov r10d,DWORD PTR [rsp+0xb0]
0x00007ffff7fbf012 <+18>: mov r11d,DWORD PTR [rsp+0xb8]
0x00007ffff7fbf01a <+26>: mov eax,r9d
0x00007ffff7fbf01d <+29>: mov rbx,rdi
0x00007ffff7fbf020 <+32>: mov r9,r8
0x00007ffff7fbf023 <+35>: sub rsp,0x8
0x00007ffff7fbf027 <+39>: movabs r14,0x7ffff7fbf290
0x00007ffff7fbf031 <+49>: lea rdi,[rsp+0x48]
0x00007ffff7fbf036 <+54>: xor r8d,r8d
0x00007ffff7fbf039 <+57>: push 0x0
0x00007ffff7fbf03b <+59>: push 0x0
0x00007ffff7fbf03d <+61>: push 0x0
0x00007ffff7fbf03f <+63>: push 0x0
0x00007ffff7fbf041 <+65>: push r11
0x00007ffff7fbf043 <+67>: push r10
0x00007ffff7fbf045 <+69>: push rax
0x00007ffff7fbf046 <+70>: call r14 ; after this call, rbx has a invalid addr - program::program::try_into_bytes[expr29](f0)
0x00007ffff7fbf049 <+73>: add rsp,0x40
0x00007ffff7fbf04d <+77>: vmovups xmm0,XMMWORD PTR [rsp+0x60]
0x00007ffff7fbf053 <+83>: mov rsi,QWORD PTR [rsp+0x58]
0x00007ffff7fbf058 <+88>: mov rax,QWORD PTR [rsp+0x40]
0x00007ffff7fbf05d <+93>: mov rcx,QWORD PTR [rsp+0x48]
0x00007ffff7fbf062 <+98>: mov rdx,QWORD PTR [rsp+0x50]
0x00007ffff7fbf067 <+103>: mov rdi,QWORD PTR [rsp+0x70]
0x00007ffff7fbf06c <+108>: mov QWORD PTR [rsp+0x20],rsi
0x00007ffff7fbf071 <+113>: mov QWORD PTR [rsp+0x38],rdi
0x00007ffff7fbf076 <+118>: vmovups XMMWORD PTR [rsp+0x28],xmm0
0x00007ffff7fbf07c <+124>: test sil,0x1
0x00007ffff7fbf080 <+128>: jne 0x7ffff7fbf0b5 <program::program::try_into_bytes(f1)+181>
0x00007ffff7fbf082 <+130>: vmovups xmm0,XMMWORD PTR [rsp+0x80]
0x00007ffff7fbf08b <+139>: mov BYTE PTR [rsp+0x78],0x0
0x00007ffff7fbf090 <+144>: mov edi,DWORD PTR [rsp+0x90]
0x00007ffff7fbf097 <+151>: mov rsi,QWORD PTR [rsp+0x78]
=> 0x00007ffff7fbf09c <+156>: mov QWORD PTR [rbx+0x10],rdx
0x00007ffff7fbf0a0 <+160>: mov QWORD PTR [rbx+0x8],rcx
0x00007ffff7fbf0a4 <+164>: mov DWORD PTR [rbx+0x30],edi This is the ax86 asm of the call r14 with some comments Dump of assembler code for function program::program::try_into_bytes[expr25](f0):
0x00007ffff7fc22a0 <+0>: push r15
0x00007ffff7fc22a2 <+2>: push r14
0x00007ffff7fc22a4 <+4>: push r12
0x00007ffff7fc22a6 <+6>: push rbx
0x00007ffff7fc22a7 <+7>: sub rsp,0x68
0x00007ffff7fc22ab <+11>: int3
=> 0x00007ffff7fc22ac <+12>: mov r14,rdi
0x00007ffff7fc22af <+15>: mov rdi,QWORD PTR [rsp+0xa8]
0x00007ffff7fc22b7 <+23>: mov r12,rsi
0x00007ffff7fc22ba <+26>: inc r12
0x00007ffff7fc22bd <+29>: mov r15,rcx
0x00007ffff7fc22c0 <+32>: mov rbx,rdx
0x00007ffff7fc22c3 <+35>: xor eax,eax
0x00007ffff7fc22c5 <+37>: test al,al
0x00007ffff7fc22c7 <+39>: jne 0x7ffff7fc233d <program::program::try_into_bytes[expr25](f0)+157>
0x00007ffff7fc22c9 <+41>: mov esi,DWORD PTR [rsp+0x98]
0x00007ffff7fc22d0 <+48>: mov eax,DWORD PTR [rsp+0xc0]
0x00007ffff7fc22d7 <+55>: mov ecx,DWORD PTR [rsp+0xb8]
0x00007ffff7fc22de <+62>: mov edx,DWORD PTR [rsp+0xb0]
0x00007ffff7fc22e5 <+69>: lea r10,[rsp+0x48] ; this stack addr is loaded into r9
0x00007ffff7fc22ea <+74>: lea r9,[rsp+0x28] ; or this stack addr is loaded into r9
0x00007ffff7fc22ef <+79>: sub esi,DWORD PTR [rsp+0x90]
0x00007ffff7fc22f6 <+86>: cmp r8d,esi ; which depends on this
0x00007ffff7fc22f9 <+89>: cmove r9,r10 ; at this cmov
0x00007ffff7fc22fd <+93>: mov DWORD PTR [r9+0x14],ecx
0x00007ffff7fc2301 <+97>: mov DWORD PTR [r9+0x10],edx
0x00007ffff7fc2305 <+101>: mov QWORD PTR [r9+0x8],rdi
0x00007ffff7fc2309 <+105>: mov DWORD PTR [r9+0x18],eax
0x00007ffff7fc230d <+109>: mov DWORD PTR [r9+0x20],r8d
0x00007ffff7fc2311 <+113>: mov BYTE PTR [r9],0x0 ; this breaks the value stored in rbx
0x00007ffff7fc2315 <+117>: vmovups xmm0,XMMWORD PTR [r9+0x8]
0x00007ffff7fc231b <+123>: mov rax,QWORD PTR [r9]
0x00007ffff7fc231e <+126>: mov rcx,QWORD PTR [r9+0x18]
0x00007ffff7fc2322 <+130>: mov QWORD PTR [r14+0x10],r15
0x00007ffff7fc2326 <+134>: mov QWORD PTR [r14+0x8],rbx
0x00007ffff7fc232a <+138>: mov QWORD PTR [r14+0x30],rcx
0x00007ffff7fc232e <+142>: vmovups XMMWORD PTR [r14+0x20],xmm0
0x00007ffff7fc2334 <+148>: mov QWORD PTR [r14+0x18],rax
0x00007ffff7fc2338 <+152>: mov QWORD PTR [r14],r12
0x00007ffff7fc233b <+155>: jmp 0x7ffff7fc23b8 <program::program::try_into_bytes[expr25](f0)+280>
0x00007ffff7fc233d <+157>: movabs rax,0x7ffff7a0b0c0
0x00007ffff7fc2347 <+167>: call rax
0x00007ffff7fc2349 <+169>: movabs rax,0x7ffff7a0b320
0x00007ffff7fc2353 <+179>: mov esi,0x100
0x00007ffff7fc2358 <+184>: xor edi,edi
0x00007ffff7fc235a <+186>: call rax
0x00007ffff7fc235c <+188>: movabs rcx,0x7ffff7fc1020
0x00007ffff7fc2366 <+198>: vmovaps ymm0,YMMWORD PTR [rcx]
0x00007ffff7fc236a <+202>: movabs rcx,0x100000000
0x00007ffff7fc2374 <+212>: vmovups YMMWORD PTR [rax],ymm0
0x00007ffff7fc2378 <+216>: mov QWORD PTR [rsp+0x18],rcx
0x00007ffff7fc237d <+221>: mov QWORD PTR [rsp+0x10],rax
0x00007ffff7fc2382 <+226>: mov BYTE PTR [rsp+0x8],0x1
0x00007ffff7fc2387 <+231>: mov DWORD PTR [rsp+0x20],0x8
0x00007ffff7fc238f <+239>: vmovups xmm0,XMMWORD PTR [rsp+0x10]
0x00007ffff7fc2395 <+245>: mov rax,QWORD PTR [rsp+0x8]
0x00007ffff7fc239a <+250>: mov rcx,QWORD PTR [rsp+0x20]
0x00007ffff7fc239f <+255>: mov QWORD PTR [r14],r12
0x00007ffff7fc23a2 <+258>: mov QWORD PTR [r14+0x10],r15
0x00007ffff7fc23a6 <+262>: mov QWORD PTR [r14+0x30],rcx
0x00007ffff7fc23aa <+266>: vmovups XMMWORD PTR [r14+0x20],xmm0
0x00007ffff7fc23b0 <+272>: mov QWORD PTR [r14+0x18],rax
0x00007ffff7fc23b4 <+276>: mov QWORD PTR [r14+0x8],rbx
0x00007ffff7fc23b8 <+280>: mov rax,r14
0x00007ffff7fc23bb <+283>: add rsp,0x68
0x00007ffff7fc23bf <+287>: pop rbx
0x00007ffff7fc23c0 <+288>: pop r12
0x00007ffff7fc23c2 <+290>: pop r14
0x00007ffff7fc23c4 <+292>: pop r15
0x00007ffff7fc23c6 <+294>: vzeroupper
0x00007ffff7fc23c9 <+297>: ret
End of assembler dump. The register rbx seems to have a good address up till the I need to investigate more what goes on in there. But it leaves the rbx register with a bad address. Edit: it seems a stack addr is loaded into r9 at some point, and the byte 0 assigned to where it points, which messes the stack when popping rbx. |
Hello, I have some good news. I did some reverse engineering and found out some interesting stuff: The program generates the following instructions (relevant only, the others have been omitted): push rbx ; Store parent base register.
sub rsp,0x68 ; Allocate 104 bytes of locals (3* 32 bytes + 8 bytes for stack alignment).
lea r10,[rsp+0x48] ; r10 = rsp + 72 ???
cmove r9,r10 ; r9 = r10 if `i == self.len()`
mov DWORD PTR [r9+0x20],r8d ; *(r9 + 32) = r8d (i) I could explain this in detail but I'll just get to the point: the last instruction is overwriting 4 bytes of To understand why this happened let's take a look at the array's internal representation:
This gives us a struct of 28 bytes with an alignment of 8 bytes. Apparently this is wrong. The correct answer is 32 bytes, because it includes 4 bytes of padding to align the structure's end to 8 (the structure's alignment). I'm not sure why this happens here because it's not an array. This is the same behavior that C exhibits, so it must be correct. Up until now, the allocations didn't contain the extra padding. I've made a fix for that: now all generated layouts contain the padding to align them properly. |
@azteca1998 that's amazing!
But you don't have an alignment of 8 bytes without the padding right?
Alignment requirements aren't only for arrays right? All structures are usually padded in order to be aligned with the native alignment of the host machine as far as I know? |
I thought only the struct's beginning were aligned, not also the end. In this case there's no need to have padding between the fields because the most restrictive value is upfront.
Alignment requirements are for all types afaik, but I didn't know we were supposed to align the struct size too. It doesn't really make sense in my head. The thing with arrays is that having the struct size being a multiple of the alignment makes it trivial to calculate offsets, but the compilers can compute that trivially; having it outside arrays seems like a waste of space to me, but I'm probably missing some crucial information about this decision. |
As far as I know, the reason why you would want to have the total struct size correctly aligned to the native alignment of the machine is for efficient memory reads/writes. Let's say we kept the 28 bytes alignment on the struct, and store a u64 right after. On 64-bits machines, you would need to perform two reads (read at address 0x3 and 0x4 assuming addressing starts at 0x0) instead of one if aligned to 8 bytes. |
Yes, but you only need the address where something starts to be aligned, not the address where something ends. The problem was that we had an array (
The compiler, however, inserts the padding to the inner and outer structs as follows, wasting eight bytes of memory per instance:
As you can see both of them are properly aligned, that's why I don't understand the decision about padding the struct's end, but as I said before I'm probably missing some crucial information or edge case that would explain the padding. |
Oh yeah that is indeed stange... |
I'm getting an issue on the
parse_result
call at the end of the invocation ofinvoke_dynamic
. Here is the backtrace:This is from executing the test
test_execute_simple_contract
from theef-tests
repo on Kakarot.The text was updated successfully, but these errors were encountered: