Skip to content

Commit

Permalink
Merge df6e72d into 65c1927
Browse files Browse the repository at this point in the history
  • Loading branch information
vaivaswatha authored Feb 16, 2024
2 parents 65c1927 + df6e72d commit 56950c8
Show file tree
Hide file tree
Showing 18 changed files with 233 additions and 9 deletions.
3 changes: 3 additions & 0 deletions sway-ast/src/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ pub enum Intrinsic {
PtrSub,
Smo,
Not,
JmpbSsp,
}

impl fmt::Display for Intrinsic {
Expand Down Expand Up @@ -73,6 +74,7 @@ impl fmt::Display for Intrinsic {
Intrinsic::PtrSub => "ptr_sub",
Intrinsic::Smo => "smo",
Intrinsic::Not => "not",
Intrinsic::JmpbSsp => "jmpb_ssp",
};
write!(f, "{s}")
}
Expand Down Expand Up @@ -115,6 +117,7 @@ impl Intrinsic {
"__ptr_sub" => PtrSub,
"__smo" => Smo,
"__not" => Not,
"__jmpb_ssp" => JmpbSsp,
_ => return None,
})
}
Expand Down
45 changes: 45 additions & 0 deletions sway-core/src/asm_generation/fuel/fuel_asm_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> {
arg2,
arg3,
} => self.compile_wide_modular_op(instr_val, op, result, arg1, arg2, arg3),
FuelVmInstruction::JmpbSsp(offset) => self.compile_jmpb_ssp(instr_val, offset),
},
InstOp::GetElemPtr {
base,
Expand Down Expand Up @@ -1451,6 +1452,50 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> {
Ok(())
}

fn compile_jmpb_ssp(&mut self, instr_val: &Value, offset: &Value) -> Result<(), CompileError> {
let owning_span = self.md_mgr.val_to_span(self.context, *instr_val);
let offset_reg = self.value_to_register(offset)?;
let is_offset_reg = self.reg_seqr.next();
let prev_ssp_reg = self.reg_seqr.next();
let by4_reg = self.reg_seqr.next();

self.cur_bytecode.push(Op {
owning_span: owning_span.clone(),
opcode: Either::Left(VirtualOp::SUB(
prev_ssp_reg.clone(),
VirtualRegister::Constant(ConstantRegister::StackStartPointer),
offset_reg,
)),
comment: "jmpb_ssp: Compute $ssp - offset".into(),
});
self.cur_bytecode.push(Op {
owning_span: owning_span.clone(),
opcode: Either::Left(VirtualOp::SUB(
is_offset_reg.clone(),
prev_ssp_reg,
VirtualRegister::Constant(ConstantRegister::InstructionStart),
)),
comment: "jmpb_ssp: Subtract $is since $jmp adds it back.".into(),
});
self.cur_bytecode.push(Op {
owning_span: owning_span.clone(),
opcode: Either::Left(VirtualOp::DIVI(
by4_reg.clone(),
is_offset_reg.clone(),
VirtualImmediate12::new(4, Span::dummy()).unwrap(),
)),
comment: "jmpb_ssp: Divide by 4 since Jmp multiplies by 4.".into(),
});

self.cur_bytecode.push(Op {
owning_span,
opcode: Either::Left(VirtualOp::JMP(by4_reg)),
comment: "jmpb_ssp: Jump to computed value".into(),
});

Ok(())
}

fn compile_smo(
&mut self,
instr_val: &Value,
Expand Down
1 change: 1 addition & 0 deletions sway-core/src/ir_generation/const_eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1111,6 +1111,7 @@ fn const_eval_intrinsic(
| Intrinsic::StateStoreQuad
| Intrinsic::Log
| Intrinsic::Revert
| Intrinsic::JmpbSsp
| Intrinsic::Smo => Err(ConstEvalError::CannotBeEvaluatedToConst {
span: intrinsic.span.clone(),
}),
Expand Down
13 changes: 13 additions & 0 deletions sway-core/src/ir_generation/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1094,6 +1094,19 @@ impl<'eng> FnCompiler<'eng> {
.add_metadatum(context, span_md_idx);
Ok(TerminatorValue::new(val, context))
}
Intrinsic::JmpbSsp => {
let offset_val = return_on_termination_or_extract!(
self.compile_expression_to_value(context, md_mgr, &arguments[0])?
);

let span_md_idx = md_mgr.span_to_md(context, &span);
let val = self
.current_block
.append(context)
.jmpb_ssp(offset_val)
.add_metadatum(context, span_md_idx);
Ok(TerminatorValue::new(val, context))
}
Intrinsic::PtrAdd | Intrinsic::PtrSub => {
let op = match kind {
Intrinsic::PtrAdd => BinaryOpKind::Add,
Expand Down
2 changes: 1 addition & 1 deletion sway-core/src/language/ty/expression/intrinsic_function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ impl DebugWithEngines for TyIntrinsicFunctionKind {

impl DeterministicallyAborts for TyIntrinsicFunctionKind {
fn deterministically_aborts(&self, decl_engine: &DeclEngine, check_call_body: bool) -> bool {
matches!(self.kind, Intrinsic::Revert)
matches!(self.kind, Intrinsic::Revert | Intrinsic::JmpbSsp)
|| self
.arguments
.iter()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ impl ty::TyIntrinsicFunctionKind {
}
Intrinsic::Smo => type_check_smo(handler, ctx, kind, arguments, type_arguments, span),
Intrinsic::Not => type_check_not(handler, ctx, kind, arguments, type_arguments, span),
Intrinsic::JmpbSsp => {
type_check_jmpb_ssp(handler, ctx, kind, arguments, type_arguments, span)
}
}
}
}
Expand Down Expand Up @@ -1171,6 +1174,55 @@ fn type_check_revert(
))
}

/// Signature: `__jmpb_ssp(offset: u64)`
/// Description: Loads contract and transfers control to it.
/// Constraints: offset has type `u64`.
fn type_check_jmpb_ssp(
handler: &Handler,
mut ctx: TypeCheckContext,
kind: sway_ast::Intrinsic,
arguments: Vec<Expression>,
type_arguments: Vec<TypeArgument>,
span: Span,
) -> Result<(ty::TyIntrinsicFunctionKind, TypeId), ErrorEmitted> {
let type_engine = ctx.engines.te();
let engines = ctx.engines();

if arguments.len() != 1 {
return Err(handler.emit_err(CompileError::IntrinsicIncorrectNumArgs {
name: kind.to_string(),
expected: 0,
span,
}));
}

if !type_arguments.is_empty() {
return Err(handler.emit_err(CompileError::IntrinsicIncorrectNumTArgs {
name: kind.to_string(),
expected: 0,
span,
}));
}

// Type check the argument which is the jmpb_ssp offset
let mut ctx = ctx.by_ref().with_type_annotation(type_engine.insert(
engines,
TypeInfo::UnsignedInteger(IntegerBits::SixtyFour),
None,
));
let offset = ty::TyExpression::type_check(handler, ctx.by_ref(), arguments[0].clone())?;

Ok((
ty::TyIntrinsicFunctionKind {
kind,
arguments: vec![offset],
type_arguments: vec![],
span,
},
type_engine.insert(engines, TypeInfo::Tuple(vec![]), None),
))
}

/// Signature: `__ptr_add(ptr: raw_ptr, offset: u64)`
/// Description: Adds `offset` to the raw value of pointer `ptr`.
/// Constraints: None.
Expand Down
2 changes: 1 addition & 1 deletion sway-core/src/semantic_analysis/cei_pattern_analysis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -608,7 +608,7 @@ fn effects_of_intrinsic(intr: &sway_ast::Intrinsic) -> HashSet<Effect> {
StateClear | StateStoreWord | StateStoreQuad => HashSet::from([Effect::StorageWrite]),
StateLoadWord | StateLoadQuad => HashSet::from([Effect::StorageRead]),
Smo => HashSet::from([Effect::OutputMessage]),
Revert | IsReferenceType | IsStrArray | SizeOfType | SizeOfVal | SizeOfStr
Revert | JmpbSsp | IsReferenceType | IsStrArray | SizeOfType | SizeOfVal | SizeOfStr
| AssertIsStrArray | ToStrArray | Eq | Gt | Lt | Gtf | AddrOf | Log | Add | Sub | Mul
| Div | And | Or | Xor | Mod | Rsh | Lsh | PtrAdd | PtrSub | Not => HashSet::new(),
}
Expand Down
3 changes: 2 additions & 1 deletion sway-ir/src/analysis/memory_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ pub fn get_loaded_ptr_values(context: &Context, val: Value) -> Vec<Value> {
InstOp::Store { dst_val_ptr: _, .. } => vec![],
InstOp::FuelVm(FuelVmInstruction::Gtf { .. })
| InstOp::FuelVm(FuelVmInstruction::ReadRegister(_))
| InstOp::FuelVm(FuelVmInstruction::Revert(_)) => vec![],
| InstOp::FuelVm(FuelVmInstruction::Revert(_) | FuelVmInstruction::JmpbSsp(_)) => vec![],
InstOp::FuelVm(FuelVmInstruction::WideUnaryOp { arg, .. }) => vec![*arg],
InstOp::FuelVm(FuelVmInstruction::WideBinaryOp { arg1, arg2, .. })
| InstOp::FuelVm(FuelVmInstruction::WideCmpOp { arg1, arg2, .. }) => {
Expand Down Expand Up @@ -252,6 +252,7 @@ pub fn get_stored_ptr_values(context: &Context, val: Value) -> Vec<Value> {
| FuelVmInstruction::Log { .. }
| FuelVmInstruction::ReadRegister(_)
| FuelVmInstruction::Revert(_)
| FuelVmInstruction::JmpbSsp(_)
| FuelVmInstruction::Smo { .. }
| FuelVmInstruction::StateClear { .. } => vec![],
FuelVmInstruction::StateLoadQuadWord { load_val, .. } => vec![*load_val],
Expand Down
5 changes: 4 additions & 1 deletion sway-ir/src/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,10 @@ impl Block {
matches!(
i,
Instruction {
op: InstOp::Ret(..) | InstOp::FuelVm(FuelVmInstruction::Revert(..)),
op: InstOp::Ret(..)
| InstOp::FuelVm(
FuelVmInstruction::Revert(..) | FuelVmInstruction::JmpbSsp(..)
),
..
}
)
Expand Down
22 changes: 18 additions & 4 deletions sway-ir/src/instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@ pub enum FuelVmInstruction {
arg1: Value,
arg2: Value,
},
JmpbSsp(Value),
}

/// Comparison operations.
Expand Down Expand Up @@ -298,7 +299,7 @@ impl InstOp {
// These are all terminators which don't return, essentially. No type.
InstOp::Branch(_)
| InstOp::ConditionalBranch { .. }
| InstOp::FuelVm(FuelVmInstruction::Revert(..))
| InstOp::FuelVm(FuelVmInstruction::Revert(..) | FuelVmInstruction::JmpbSsp(..))
| InstOp::Ret(..) => None,

// No-op is also no-type.
Expand Down Expand Up @@ -407,7 +408,7 @@ impl InstOp {
log_val, log_id, ..
} => vec![*log_val, *log_id],
FuelVmInstruction::ReadRegister(_) => vec![],
FuelVmInstruction::Revert(v) => vec![*v],
FuelVmInstruction::Revert(v) | FuelVmInstruction::JmpbSsp(v) => vec![*v],
FuelVmInstruction::Smo {
recipient,
message,
Expand Down Expand Up @@ -544,6 +545,7 @@ impl InstOp {
}
FuelVmInstruction::ReadRegister { .. } => (),
FuelVmInstruction::Revert(revert_val) => replace(revert_val),
FuelVmInstruction::JmpbSsp(contr_id) => replace(contr_id),
FuelVmInstruction::Smo {
recipient,
message,
Expand Down Expand Up @@ -629,7 +631,7 @@ impl InstOp {
| InstOp::FuelVm(FuelVmInstruction::StateLoadQuadWord { .. })
| InstOp::FuelVm(FuelVmInstruction::StateStoreQuadWord { .. })
| InstOp::FuelVm(FuelVmInstruction::StateStoreWord { .. })
| InstOp::FuelVm(FuelVmInstruction::Revert(..))
| InstOp::FuelVm(FuelVmInstruction::Revert(..) | FuelVmInstruction::JmpbSsp(..))
| InstOp::MemCopyBytes { .. }
| InstOp::MemCopyVal { .. }
| InstOp::Store { .. }
Expand Down Expand Up @@ -664,7 +666,7 @@ impl InstOp {
InstOp::Branch(_)
| InstOp::ConditionalBranch { .. }
| InstOp::Ret(..)
| InstOp::FuelVm(FuelVmInstruction::Revert(..))
| InstOp::FuelVm(FuelVmInstruction::Revert(..) | FuelVmInstruction::JmpbSsp(..))
)
}
}
Expand Down Expand Up @@ -1072,6 +1074,18 @@ impl<'a, 'eng> InstructionInserter<'a, 'eng> {
revert_val
}

pub fn jmpb_ssp(self, offset: Value) -> Value {
let ldc_exec = Value::new_instruction(
self.context,
self.block,
InstOp::FuelVm(FuelVmInstruction::JmpbSsp(offset)),
);
self.context.blocks[self.block.0]
.instructions
.push(ldc_exec);
ldc_exec
}

pub fn smo(self, recipient: Value, message: Value, message_size: Value, coins: Value) -> Value {
insert_instruction!(
self,
Expand Down
1 change: 1 addition & 0 deletions sway-ir/src/optimize/fn_dedup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ fn hash_fn(context: &Context, function: Function, eq_class: &mut EqClass) -> u64
crate::FuelVmInstruction::Log { log_ty, .. } => log_ty.hash(state),
crate::FuelVmInstruction::ReadRegister(reg) => reg.hash(state),
crate::FuelVmInstruction::Revert(_)
| crate::FuelVmInstruction::JmpbSsp(_)
| crate::FuelVmInstruction::Smo { .. }
| crate::FuelVmInstruction::StateClear { .. }
| crate::FuelVmInstruction::StateLoadQuadWord { .. }
Expand Down
3 changes: 3 additions & 0 deletions sway-ir/src/optimize/inline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,9 @@ fn inline_instruction(
new_block.append(context).read_register(reg)
}
FuelVmInstruction::Revert(val) => new_block.append(context).revert(map_value(val)),
FuelVmInstruction::JmpbSsp(offset) => {
new_block.append(context).jmpb_ssp(map_value(offset))
}
FuelVmInstruction::Smo {
recipient,
message,
Expand Down
11 changes: 11 additions & 0 deletions sway-ir/src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ mod ir_builder {
/ op_read_register()
/ op_ret()
/ op_revert()
/ op_jmpb_ssp()
/ op_smo()
/ op_state_load_quad_word()
/ op_state_load_word()
Expand Down Expand Up @@ -362,6 +363,11 @@ mod ir_builder {
IrAstOperation::Revert(vn)
}

rule op_jmpb_ssp() -> IrAstOperation
= "jmpb_ssp" _ vn:id() {
IrAstOperation::JmpbSsp(vn)
}

rule op_smo() -> IrAstOperation
= "smo" _
recipient_and_message:id() comma() message_size:id() comma() output_index:id() comma() coins:id() _ {
Expand Down Expand Up @@ -722,6 +728,7 @@ mod ir_builder {
ReadRegister(String),
Ret(IrAstTy, String),
Revert(String),
JmpbSsp(String),
Smo(String, String, String, String),
StateClear(String, String),
StateLoadQuadWord(String, String, String),
Expand Down Expand Up @@ -1344,6 +1351,10 @@ mod ir_builder {
.append(context)
.revert(*val_map.get(&ret_val_name).unwrap())
.add_metadatum(context, opt_metadata),
IrAstOperation::JmpbSsp(offset_name) => block
.append(context)
.jmpb_ssp(*val_map.get(&offset_name).unwrap())
.add_metadatum(context, opt_metadata),
IrAstOperation::Smo(recipient, message, message_size, coins) => block
.append(context)
.smo(
Expand Down
6 changes: 6 additions & 0 deletions sway-ir/src/printer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -656,6 +656,12 @@ fn instruction_to_doc<'a>(
Doc::text(format!("revert {}", namer.name(context, v),))
.append(md_namer.md_idx_to_doc(context, metadata)),
)),
FuelVmInstruction::JmpbSsp(offset) => {
maybe_constant_to_doc(context, md_namer, namer, offset).append(Doc::line(
Doc::text(format!("jmpb_ssp {}", namer.name(context, offset),))
.append(md_namer.md_idx_to_doc(context, metadata)),
))
}
FuelVmInstruction::Smo {
recipient,
message,
Expand Down
2 changes: 1 addition & 1 deletion sway-ir/src/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ impl Value {
InstOp::Branch(_)
| InstOp::ConditionalBranch { .. }
| InstOp::Ret(_, _)
| InstOp::FuelVm(FuelVmInstruction::Revert(_))
| InstOp::FuelVm(FuelVmInstruction::Revert(_) | FuelVmInstruction::JmpbSsp(_))
),
ValueDatum::Argument(..) | ValueDatum::Configurable(..) | ValueDatum::Constant(..) => {
false
Expand Down
1 change: 1 addition & 0 deletions sway-ir/src/verify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,7 @@ impl<'a, 'eng> InstructionVerifier<'a, 'eng> {
log_id,
} => self.verify_log(log_val, log_ty, log_id)?,
FuelVmInstruction::ReadRegister(_) => (),
FuelVmInstruction::JmpbSsp(_) => (),
FuelVmInstruction::Revert(val) => self.verify_revert(val)?,
FuelVmInstruction::Smo {
recipient,
Expand Down
8 changes: 8 additions & 0 deletions test/src/ir_generation/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,14 @@ Both checks against IR and ASM may be provided in the same Sway test source file
To delimit between checks against IR and those against ASM the source file may be split into sections using delimiting marker text.

* `::check-ir::` marks the beginning of the IR checks.
* `::check-ir-optimized::` marks the begingging of the optimized IR checks.
* `::check-asm::` marks the beginning of the ASM checks.

Optimized IR chekcer can be configured with `pass: <PASSNAME or o1>`. When
`o1` is chosen, all the configured passes are chosen automatically.
```
::check-ir-optimized::
pass: o1
```

The sections may go in either order. If there are no markers then it is assumed that all checks are for IR.
Loading

0 comments on commit 56950c8

Please sign in to comment.