// RUN: --target solana --emit cfg -Onone --no-cse
contract testing {
// BEGIN-CHECK: testing::testing::function::calls_and_unreachable__uint64_uint64
function calls_and_unreachable(uint64 a, uint64 b) public pure {
assembly {
function test1(c : u128, d) {
let y := mul(c, d)
}
// CHECK: = call testing::yul_function_0::test1 (zext uint128 (arg #0)), (zext uint256 (arg #1))
test1(a, b)
// CHECK: assert-failure
invalid()
// NOT-CHECK: ty:uint256 %x =
let x := mul(a, b)
}
}
// BEGIN-CHECK: testing::testing::function::yul_block__uint16_int16
function yul_block(uint16 a, int16 b) public pure {
assembly {
// CHECK: ty:uint256 %x = (sext uint256 ((sext int24 (arg #1)) >> (zext int24 (arg #0))))
let x := shr(a, b)
{
// CHECK: ty:uint256 %y = ((sext uint256 ((sext int24 (arg #1)) >> (zext int24 (arg #0)))) * (zext uint256 (arg #0)))
let y := mul(x, a)
// CHECK: ty:uint8 %g = uint8((unsigned less int256(((sext uint256 ((sext int24 (arg #1)) >> (zext int24 (arg #0)))) * (zext uint256 (arg #0)))) < (sext int256 (arg #1))))
let g : u8 := lt(y, b)
}
}
}
// BEGIN-CHECK: testing::testing::function::variable_declaration__bool_uint8
function variable_declaration(bool a, uint8 b) public pure {
assembly {
function multiple() -> ret1, ret2 : s32 {
ret1 := 4
ret2 := 6
}
function unique() -> ret3 {
ret3 := 6
}
// CHECK: %ret3.temp.40 = call testing::yul_function_2::unique
// CHECK: ty:uint256 %c = %ret3.temp.40
let c := unique()
// CHECK: %ret1.temp.41, %ret2.temp.42 = call testing::yul_function_1::multiple
// CHECK: ty:uint256 %d = %ret1.temp.41
// CHECK: ty:int8 %e = (trunc int8 %ret2.temp.42)
let d, e : s8 := multiple()
// CHECK: ty:uint256 %f = uint256(((arg #0) == bool 0))
let f := iszero(a)
// CHECK: ty:uint256 %g = undef
// CHECK: ty:uint256 %h = undef
// CHECK: ty:uint256 %i = undef
let g, h, i
}
}
// BEGIN-CHECK: testing::testing::function::if_statement__bool
function if_statement(bool a) public pure {
assembly {
let x := 5
// CHECK: branchcond (arg #0), block1, block2
if a {
// CHECK: block1: # then
// CHECK: ty:uint256 %x = (uint256((arg #0)) + uint256 5)
x := add(a, x)
// CHECK: ty:bool %a = false
a := false
// CHECK: branch block2
}
// CHECK: block2: # endif
// CHECK: branchcond (uint256 0 != %x), block3, block4
if x {
// CHECK: block3: # then
// CHECK: ty:uint256 %x = uint256 5
x := 5
// CHECK: branch block4
}
// CHECK: block4: # endif
// CHECK: branchcond (unsigned less %x < uint256 3), block5, block6
if lt(x, 3) {
// CHECK: block5: # then
// CHECK: ty:uint256 %x = uint256 4
x := 4
// CHECK: branch block6
}
// CHECK: block6: # endif
// CHECK: branchcond (unsigned less %x < uint256 3), block7, block8
if lt(x, 3) {
// CHECK: block7: # then
// CHECK: ty:uint256 %x = uint256 6
x := 6
// CHECK: assert-failure
invalid()
// NOT-CHECK: branch
}
// CHECK: branchcond (%x == uint256 3), block9, block10
if eq(x, 3) {
// CHECK: block9: # then
// CHECK: branch block10
}
// CHECK: block10: # endif
// CHECK: ty:uint256 %x = uint256 4
x := 4
}
}
// BEGIN-CHECK: testing::testing::function::for_statement__bool
function for_statement(bool a) public pure {
assembly {
for {
// CHECK: ty:uint256 %i = uint256 1
let i := 1
// CHECK: branch block1
// CHECK: block1: # cond
// CHECK: branchcond (uint256 0 != (%i + uint256 1)), block3, block4
} add(i, 1) {
// CHECK: block2: # next
// CHECK: ty:uint256 %i = (%i - uint256 1)
i := sub(i, 1)
// CHECK: branch block1
} {
// CHECK: block3: # body
// CHECK: ty:uint256 %i = (%i << uint256 1)
i := mul(i, 2)
// CHECK: branch block2
}
// CHECK: block4: # end_for
for {
// CHECK: ty:uint256 %i.27 = uint256 1
// CHECK: branch block5
let i := 1
// CHECK: block5: # cond
// CHECK: branchcond (unsigned less %i.27 < uint256 10), block7, block8
} lt(i, 10) {
// CHECK: block6: # next
i := add(i, 1)
// CHECK: ty:uint256 %i.27 = (%i.27 + uint256 1)
// CHECK: branch block5
} {
// CHECK: block7: # body
// CHECK: ty:uint256 %i.27 = (uint256 2 >> %i.27)
i := shr(i, 2)
// CHECK: branch block6
}
// CHECK: block8: # end_for
for {
// CHECK: ty:uint256 %i.28 = uint256 1
let i := 1
// CHECK: branch block9
// CHECK: block9: # cond
// CHECK: branchcond %a, block11, block12
} a {
// CHECK: block10: # next
// CHECK: ty:uint256 %i.28 = (uint256(%a) + uint256 1)
i := add(a, 1)
// CHECK: ty:bool %a = false
a := false
} {
// CHECK: block11: # body
// CHECK: ty:bool %a = (uint256 0 != (%i.28 + uint256 2))
a := add(i, 2)
// CHECK: branch block10
}
// CHECK: block12: # end_for
for {
// CHECK: ty:uint256 %i.29 = uint256 2
let i := 2
// CHECK: branch block13
// CHECK: block13: # cond
// CHECK: branchcond (uint256 2 == uint256 0), block15, block16
} eq(i, 0) {
// CHECK: block14: # next
// NOT-CHECK: ty:uint256 %i.29 =
i := sub(i, 2)
} {
// CHECK: block15: # body
i := add(i, 3)
// CHECK: ty:uint256 %i.29 = uint256 5
invalid()
// CHECK: assert-failure
// NOT-CHECK: branch
}
// CHECK: block16: # end_for
for {
// CHECK: ty:uint256 %j = uint256 2
let j := 2
// CHECK: branch block17
// CHECK: block17: # cond
// CHECK: branchcond (uint256 2 == uint256 3), block19, block20
} eq(j, 3) {
// CHECK: block18: # next
j := shr(j, 2)
// CHECK: ty:uint256 %j = (uint256 2 >> %j)
invalid()
// CHECK: assert-failure
} {
// CHECK: block19: # body
j := sar(j, 3)
// CHECK: branch block18
}
// CHECK: block20: # end_for
for {
// CHECK: ty:uint256 %i.31 = uint256 0
let i := 0
// CHECK: branch block21
// CHECK: block21: # cond
// CHECK: branchcond (unsigned less %i.31 < uint256 10), block23, block24
} lt(i, 10) {
// CHECK: block22: # next
i := add(i, 1)
// CHECK: ty:uint256 %i.31 = (%i.31 + uint256 1)
// CHECK: branch block21
} {
// CHECK: block23: # body
for {
// CHECK: ty:uint256 %j.32 = uint256 0
let j :=0
// CHECK: branch block25
// ---- block 24 contains the for-loop with the invalid function
// CHECK: block24: # end_for
// CHECK: ty:uint256 %i.33 = uint256 2
// CHECK: assert-failure
// NOT-CHECK: branch
// CHECK: block25: # cond
// CHECK: branchcond (unsigned less %j.32 < uint256 10), block27, block28
} lt(j, 10) {
// CHECK: ty:uint256 %j.32 = (%j.32 + uint256 1)
j := add(j, 1)
// CHECK: branch block25
} {
// CHECK: block27: # body
// CHECK: ty:bool %a = (uint256 0 != (%i.31 + %j.32))
a := add(i, j)
// CHECK: branch block26
}
// CHECK: block28: # end_for
// CHECK: branch block22
}
for {
let i := 2
invalid()
} lt(3, 4) {
i := add(i, 1)
} {
i := sub(i, 2)
}
}
}
// BEGIN-CHECK: testing::testing::function::break_statement
function break_statement() public pure {
assembly {
for {let i := 1
// CHECK: ty:uint256 %i = uint256 1
// CHECK: branch block1
// CHECK: block1: # cond
// CHECK: branchcond (unsigned less %i < uint256 10), block3, block4
} lt(i, 10) {i := add(i, 1)
// CHECK: block2: # next
// CHECK: ty:uint256 %i = (%i + uint256 1)
// CHECK: branch block1
} {
// CHECK: block3: # body
i := shr(i, 2)
// CHECK: ty:uint256 %i = (uint256 2 >> %i)
// CHECK: branchcond (unsigned more %i > uint256 10), block5, block6
if gt(i, 10) {
break
}
}
// CHECK: block4: # end_for
// CHECK: return
// IF-block:
// CHECK: block5: # then
// CHECK: branch block4
// End of for for loop after IF
// CHECK: block6: # endif
// CHECK: branch block2
}
}
// BEGIN-CHECK: testing::testing::function::break_nested_for
function break_nested_for() public pure {
assembly {
for {
// CHECK: ty:uint256 %i = uint256 1
let i := 1
// CHECK: branch block1
// CHECK: branchcond (unsigned less %i < uint256 10), block3, block4
} lt(i, 10) {
// CHECK: block2: # next
i := add(i, 1)
// CHECK: ty:uint256 %i = (%i + uint256 1)
// CHECK: branch block1
} {
for {
// CHECK: block3: # body
let j := 2
// CHECK: ty:uint256 %j = uint256 2
// CHECK: branch block5
} lt(j, 10) {
// after outer for:
// CHECK: block4: # end_for
// CHECK: return
// inner for condition
// CHECK: block5: # cond
// CHECK: branchcond (unsigned less %j < uint256 10), block7, block8
// CHECK: block6: # next
// CHECK: ty:uint256 %j = (%j + uint256 1)
// CHECK: branch block5
j := add(j, 1)
} {
// CHECK: block7: # body
// CHECK: branchcond (unsigned more %j > uint256 5), block9, block10
if gt(j, 5) {
break
}
// After inner for:
// CHECK: block8: # end_for
// CHECK: branchcond (unsigned more %i > uint256 5), block11, block12
// Inside inner if:
// CHECK: block9: # then
// CHECK: branch block8
// After inner if:
// CHECK: block10: # endif
// CHECK: ty:uint256 %j = (%i - uint256 2)
j := sub(i, 2)
// CHECK: branch block6
}
if gt(i, 5) {
// CHECK: block11: # then
break
// CHECK: branch block4
}
// CHECK: block12: # endif
// CHECK: ty:uint256 %i = (%i - uint256 4)
i := sub(i, 4)
// CHECK: branch block2
}
}
}
// BEGIN-CHECK: testing::testing::function::continue_statement
function continue_statement() public pure {
assembly {
for {let i := 1
// CHECK: ty:uint256 %i = uint256 1
// CHECK: branch block1
// CHECK: block1: # cond
// CHECK: branchcond (unsigned less %i < uint256 10), block3, block4
} lt(i, 10) {i := add(i, 1)
// CHECK: block2: # next
// CHECK: ty:uint256 %i = (%i + uint256 1)
// CHECK: branch block1
} {
// CHECK: block3: # body
i := shr(i, 2)
// CHECK: ty:uint256 %i = (uint256 2 >> %i)
// CHECK: branchcond (unsigned more %i > uint256 10), block5, block6
if gt(i, 10) {
continue
}
}
// CHECK: block4: # end_for
// CHECK: return
// IF-block:
// CHECK: block5: # then
// CHECK: branch block2
// End of for for loop after IF
// CHECK: block6: # endif
// CHECK: branch block2
}
}
// BEGIN-CHECK: testing::testing::function::continue_nested_for
function continue_nested_for() public pure {
assembly {
for {
// CHECK: ty:uint256 %i = uint256 1
let i := 1
// CHECK: branch block1
// CHECK: branchcond (unsigned less %i < uint256 10), block3, block4
} lt(i, 10) {
// CHECK: block2: # next
i := add(i, 1)
// CHECK: ty:uint256 %i = (%i + uint256 1)
// CHECK: branch block1
} {
for {
// CHECK: block3: # body
let j := 2
// CHECK: ty:uint256 %j = uint256 2
// CHECK: branch block5
} lt(j, 10) {
// after outer for:
// CHECK: block4: # end_for
// CHECK: return
// inner for condition
// CHECK: block5: # cond
// CHECK: branchcond (unsigned less %j < uint256 10), block7, block8
// CHECK: block6: # next
// CHECK: ty:uint256 %j = (%j + uint256 1)
// CHECK: branch block5
j := add(j, 1)
} {
// CHECK: block7: # body
// CHECK: branchcond (unsigned more %j > uint256 5), block9, block10
if gt(j, 5) {
continue
}
// After inner for:
// CHECK: block8: # end_for
// CHECK: branchcond (unsigned more %i > uint256 5), block11, block12
// Inside inner if:
// CHECK: block9: # then
// CHECK: branch block6
// After inner if:
// CHECK: block10: # endif
// CHECK: ty:uint256 %j = (%i - uint256 2)
j := sub(i, 2)
// CHECK: branch block6
}
if gt(i, 5) {
// CHECK: block11: # then
continue
// CHECK: branch block2
}
// CHECK: block12: # endif
// CHECK: ty:uint256 %i = (%i - uint256 4)
i := sub(i, 4)
// CHECK: branch block2
}
}
}
}