Skip to content

Commit

Permalink
- IR printer changes
Browse files Browse the repository at this point in the history
- IR + asm unit test
- E2E test to check the JSON ABI
- Enhance IR verifier
- Documentation of __smo in the Sway Book
  • Loading branch information
mohammadfawaz committed Dec 12, 2022
1 parent 73d3a5a commit af776ee
Show file tree
Hide file tree
Showing 13 changed files with 444 additions and 20 deletions.
10 changes: 10 additions & 0 deletions docs/book/src/reference/compiler_intrinsics.md
Original file line number Diff line number Diff line change
Expand Up @@ -183,3 +183,13 @@ __ptr_sub(ptr: raw_ptr, offset: u64)
**Constraints:** None.

___

```sway
__smo<T>(recipient: b256, data: T, output_index: u64, coins: u64)
```

**Description:** Sends a message `data` of arbitrary type `T` and `coins` amount of the base asset to address `recipient`. This intrinsic assumes that an OutputMessage is available at index

**Constraints:** None.

___
4 changes: 4 additions & 0 deletions sway-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,10 @@ pub(crate) fn compile_ast_to_ir_to_asm(
errors.extend(e);
}

if build_config.print_ir {
tracing::info!("{}", ir);
}

// Now we're working with all functions in the module.
let all_functions = ir
.module_iter()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1051,7 +1051,6 @@ fn type_check_ptr_ops(
/// to address `recipient`. This intrinsic assumes that an OutputMessage is available at index
/// `output_index`.
/// Constraints: None.
///
fn type_check_smo(
mut ctx: TypeCheckContext,
kind: sway_ast::Intrinsic,
Expand Down Expand Up @@ -1082,17 +1081,7 @@ fn type_check_smo(
return err(warnings, errors);
}

// Type check the first argument which is the recipient address, so it has to be a `b256`.
let mut ctx = ctx
.by_ref()
.with_type_annotation(type_engine.insert_type(TypeInfo::B256));
let recipient = check!(
ty::TyExpression::type_check(ctx.by_ref(), arguments[0].clone()),
return err(warnings, errors),
warnings,
errors
);

// Type check the type argument
let type_argument = type_arguments.get(0).map(|targ| {
let mut ctx = ctx
.by_ref()
Expand Down Expand Up @@ -1127,7 +1116,19 @@ fn type_check_smo(
}
});

// Type check the second argument which is the data, which can be anything.
// Type check the first argument which is the recipient address, so it has to be a `b256`.
let mut ctx = ctx
.by_ref()
.with_type_annotation(type_engine.insert_type(TypeInfo::B256));
let recipient = check!(
ty::TyExpression::type_check(ctx.by_ref(), arguments[0].clone()),
return err(warnings, errors),
warnings,
errors
);

// Type check the second argument which is the data, which can be anything. If a type
// argument is provided, make sure that it matches the type of the data.
let mut ctx = ctx.by_ref().with_type_annotation(
type_argument
.clone()
Expand Down
15 changes: 15 additions & 0 deletions sway-ir/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ pub enum IrError {
VerifyLogId,
VerifyMismatchedLoggedTypes,
VerifyRevertCodeBadType,
VerifySmoRecipientBadType,
VerifySmoBadRecipientAndMessageType,
VerifySmoMessageSize,
VerifySmoCoins,
VerifySmoOutputIndex,
Expand Down Expand Up @@ -324,6 +326,19 @@ impl fmt::Display for IrError {
"Verification failed: error code for revert must be a u64."
)
}
IrError::VerifySmoRecipientBadType => {
write!(
f,
"Verification failed: the struct `recipient_and_message` of `smo` must have a `b256` \
as its first field."
)
}
IrError::VerifySmoBadRecipientAndMessageType => {
write!(
f,
"Verification failed: `recipient_and_message` of `smo` must have a struct"
)
}
IrError::VerifySmoMessageSize => {
write!(
f,
Expand Down
11 changes: 5 additions & 6 deletions sway-ir/src/instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,12 +124,11 @@ pub enum Instruction {
Ret(Value, Type),
/// Revert VM execution.
Revert(Value),
/// Sends `message_data` of type `message_ty` and a `coins` amount of the base asset to
/// `recipient`.
/// - Assume the existence of an `OutputMessage` at `output_index`
/// - Also accepts a unique ID describing the `smo` instance.
/// - `recipient` must be of type `b256`
/// - `output_index`, `coins`, and `message_id` must be of type `U64`.
/// - Sends a message to an output via the `smo` FuelVM instruction. The first operand must be
/// a struct with the first field being a `B256` representing the recipient. The rest of the
/// struct is the message data being sent.
/// - Assumes the existence of an `OutputMessage` at `output_index`
/// - `message_size`, `output_index`, and `coins` must be of type `U64`.
Smo {
recipient_and_message: Value,
message_size: Value,
Expand Down
22 changes: 22 additions & 0 deletions sway-ir/src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ mod ir_builder {
/ op_read_register()
/ op_ret()
/ op_revert()
/ op_smo()
/ op_state_load_quad_word()
/ op_state_load_word()
/ op_state_store_quad_word()
Expand Down Expand Up @@ -314,6 +315,12 @@ mod ir_builder {
IrAstOperation::Revert(vn)
}

rule op_smo() -> IrAstOperation
= "smo" _
recipient_and_message:id() comma() message_size:id() comma() output_index:id() comma() coins:id() _ {
IrAstOperation::Smo(recipient_and_message, message_size, output_index, coins)
}

rule op_state_load_quad_word() -> IrAstOperation
= "state_load_quad_word" _ ptr() dst:id() comma() "key" _ ptr() _ key:id() {
IrAstOperation::StateLoadQuadWord(dst, key)
Expand Down Expand Up @@ -668,6 +675,7 @@ mod ir_builder {
ReadRegister(String),
Ret(IrAstTy, String),
Revert(String),
Smo(String, String, String, String),
StateLoadQuadWord(String, String),
StateLoadWord(String),
StateStoreQuadWord(String, String),
Expand Down Expand Up @@ -1223,6 +1231,20 @@ mod ir_builder {
.ins(context)
.revert(*val_map.get(&ret_val_name).unwrap())
.add_metadatum(context, opt_metadata),
IrAstOperation::Smo(
recipient_and_message,
message_size,
output_index,
coins,
) => block
.ins(context)
.smo(
*val_map.get(&recipient_and_message).unwrap(),
*val_map.get(&message_size).unwrap(),
*val_map.get(&output_index).unwrap(),
*val_map.get(&coins).unwrap(),
)
.add_metadatum(context, opt_metadata),
IrAstOperation::StateLoadQuadWord(dst, key) => block
.ins(context)
.state_load_quad_word(
Expand Down
16 changes: 15 additions & 1 deletion sway-ir/src/verify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -711,19 +711,33 @@ impl<'a> InstructionVerifier<'a> {

fn verify_smo(
&self,
_recipient_and_message: &Value,
recipient_and_message: &Value,
message_size: &Value,
output_index: &Value,
coins: &Value,
) -> Result<(), IrError> {
// Check that the first operand is a struct with the first field being a `b256`
// representing the recipient address
if let Some(Type::Struct(agg)) = recipient_and_message.get_stripped_ptr_type(self.context) {
let fields = self.context.aggregates[agg.0].field_types();
if fields.is_empty() || !fields[0].eq(self.context, &Type::B256) {
return Err(IrError::VerifySmoRecipientBadType);
}
} else {
return Err(IrError::VerifySmoBadRecipientAndMessageType);
}

// Check that the second operand is a `u64` representing the message size.
if !matches!(message_size.get_type(self.context), Some(Type::Uint(64))) {
return Err(IrError::VerifySmoMessageSize);
}

// Check that the third operand is a `u64` representing the output index.
if !matches!(output_index.get_type(self.context), Some(Type::Uint(64))) {
return Err(IrError::VerifySmoOutputIndex);
}

// Check that the fourth operand is a `u64` representing the amount of coins being sent.
if !matches!(coins.get_type(self.context), Some(Type::Uint(64))) {
return Err(IrError::VerifySmoCoins);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[[package]]
name = 'smo'
source = 'member'
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[project]
authors = ["Fuel Labs <contact@fuel.sh>"]
entry = "main.sw"
implicit-std = false
license = "Apache-2.0"
name = "smo"

[dependencies]
Loading

0 comments on commit af776ee

Please sign in to comment.