Skip to content

Commit

Permalink
Merge pull request #400 from Concordium/sign-extension
Browse files Browse the repository at this point in the history
Add support for sign extension instructions.
  • Loading branch information
abizjak authored Jun 26, 2023
2 parents f674972 + 25e0244 commit 55f86ba
Show file tree
Hide file tree
Showing 26 changed files with 376 additions and 42 deletions.
24 changes: 24 additions & 0 deletions haskell-src/Concordium/Types/ProtocolVersion.hs
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,8 @@ module Concordium.Types.ProtocolVersion (
supportsChainQueryContracts,
supportsAccountAliases,
supportsDelegationPV,
supportsSignExtensionInstructions,
supportsGlobalsInInitSections,

-- * Defunctionalisation symbols
P1Sym0,
Expand Down Expand Up @@ -500,3 +502,25 @@ supportsChainQueryContracts spv = case spv of
SP4 -> False
SP5 -> True
SP6 -> True

-- |Whether the protocol version supports sign extension instructions for V1
-- contracts. (Supported in 'P6' and onwards)
supportsSignExtensionInstructions :: SProtocolVersion pv -> Bool
supportsSignExtensionInstructions spv = case spv of
SP1 -> False
SP2 -> False
SP3 -> False
SP4 -> False
SP5 -> False
SP6 -> True

-- |Whether the protocol version allows globals in data and element sections of
-- Wasm modules for V1 contracts. (Supported before 'P6')
supportsGlobalsInInitSections :: SProtocolVersion pv -> Bool
supportsGlobalsInInitSections spv = case spv of
SP1 -> True
SP2 -> True
SP3 -> True
SP4 -> True
SP5 -> True
SP6 -> False
Binary file not shown.
8 changes: 8 additions & 0 deletions smart-contracts/testdata/contracts/v1/i32.extend16_s.wat
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
;; The only purpose of this contract is to check
;; whether i32.extend16_s instruction is allowed in the module.
(module
;; Init contract
(func $init_contract (export "init_contract") (param i64) (result i32)
(i32.extend16_s (i32.const 3))
(return (i32.const 0))) ;; Successful init
)
Binary file not shown.
8 changes: 8 additions & 0 deletions smart-contracts/testdata/contracts/v1/i32.extend8_s.wat
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
;; The only purpose of this contract is to check
;; whether i32.extend8_s instruction is allowed in the module.
(module
;; Init contract
(func $init_contract (export "init_contract") (param i64) (result i32)
(i32.extend8_s (i32.const 3))
(return (i32.const 0))) ;; Successful init
)
Binary file not shown.
8 changes: 8 additions & 0 deletions smart-contracts/testdata/contracts/v1/i64.extend16_s.wat
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
;; The only purpose of this contract is to check
;; whether i64.extend16_s instruction is allowed in the module.
(module
;; Init contract
(func $init_contract (export "init_contract") (param i64) (result i32)
(i64.extend16_s (i64.const 3))
(return (i32.const 0))) ;; Successful init
)
Binary file not shown.
8 changes: 8 additions & 0 deletions smart-contracts/testdata/contracts/v1/i64.extend32_s.wat
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
;; The only purpose of this contract is to check
;; whether i64.extend32_s instruction is allowed in the module.
(module
;; Init contract
(func $init_contract (export "init_contract") (param i64) (result i32)
(i64.extend32_s (i64.const 3))
(return (i32.const 0))) ;; Successful init
)
Binary file not shown.
8 changes: 8 additions & 0 deletions smart-contracts/testdata/contracts/v1/i64.extend8_s.wat
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
;; The only purpose of this contract is to check
;; whether i64.extend8_s instruction is allowed in the module.
(module
;; Init contract
(func $init_contract (export "init_contract") (param i64) (result i32)
(i64.extend8_s (i64.const 3))
(return (i32.const 0))) ;; Successful init
)
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,40 @@
)
)

(func (export "i32.extend8_s")
(loop $loop
(i32.extend8_s (i32.const 312312))
(br $loop)
)
)

(func (export "i32.extend16_s")
(loop $loop
(i32.extend16_s (i32.const 312312))
(br $loop)
)
)

(func (export "i64.extend8_s")
(loop $loop
(i64.extend8_s (i64.const 312312))
(br $loop)
)
)

(func (export "i64.extend16_s")
(loop $loop
(i64.extend16_s (i64.const 312312))
(br $loop)
)
)

(func (export "i64.extend32_s")
(loop $loop
(i64.extend32_s (i64.const 312312))
(br $loop)
)
)

;; indirectly call an empty function with 100 arguments
(func (export "call_empty_function_100")
Expand Down
5 changes: 5 additions & 0 deletions smart-contracts/wasm-chain-integration/benches/wasm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,11 @@ pub fn criterion_benchmark(c: &mut Criterion) {
exec("i64.rem_s", &[]);
exec("i64.rem_u", &[]);
exec("i32.wrap_i64", &[]);
exec("i32.extend8_s", &[]);
exec("i32.extend16_s", &[]);
exec("i64.extend8_s", &[]);
exec("i64.extend16_s", &[]);
exec("i64.extend32_s", &[]);
group.finish();
}

Expand Down
5 changes: 4 additions & 1 deletion smart-contracts/wasm-chain-integration/src/v1/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,8 @@ unsafe extern "C" fn validate_and_process_v1(
support_upgrade: u8,
// Allow globals in initialization expressions for data and element sections.
allow_globals_in_init: u8,
// Allow sign extension instructions.
allow_sign_extension_instr: u8,
wasm_bytes_ptr: *const u8,
wasm_bytes_len: size_t,
// this is the total length of the output byte array
Expand All @@ -392,7 +394,8 @@ unsafe extern "C" fn validate_and_process_v1(
let wasm_bytes = slice_from_c_bytes!(wasm_bytes_ptr, wasm_bytes_len);
match utils::instantiate_with_metering::<ProcessedImports, _>(
ValidationConfig {
allow_globals_in_init: allow_globals_in_init != 0,
allow_globals_in_init: allow_globals_in_init != 0,
allow_sign_extension_instr: allow_sign_extension_instr != 0,
},
&ConcordiumAllowedImports {
support_upgrade: support_upgrade == 1,
Expand Down
6 changes: 5 additions & 1 deletion smart-contracts/wasm-transform/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@
## Unreleased changes

- `validate_module` is now parameterized by `ValidationConfig` which determines
which Wasm features should be allowed.
which Wasm features should be allowed. The currently supported configurable features are
- allow access to globals (defined in the current module) in data and element
initialization sections.
- allow instructions defined in the [sign extension operators](https://github.com/WebAssembly/sign-extension-ops/blob/master/proposals/sign-extension-ops/Overview.md)
Wasm proposal.

## concordium-wasm 2.0.0 (2023-06-16)

Expand Down
22 changes: 22 additions & 0 deletions smart-contracts/wasm-transform/src/artifact.rs
Original file line number Diff line number Diff line change
Expand Up @@ -576,6 +576,13 @@ pub enum InternalOpcode {
I32WrapI64,
I64ExtendI32S,
I64ExtendI32U,

// Sign extension instructions, optionally supported depending on the protocol version.
I32Extend8S,
I32Extend16S,
I64Extend8S,
I64Extend16S,
I64Extend32S,
}

/// Result of compilation. Either Ok(_) or an error indicating the reason.
Expand Down Expand Up @@ -1147,6 +1154,21 @@ impl Handler<&OpCode> for BackPatch {
OpCode::I64ExtendI32U => {
self.out.push(I64ExtendI32U);
}
OpCode::I32Extend8S => {
self.out.push(I32Extend8S);
}
OpCode::I32Extend16S => {
self.out.push(I32Extend16S);
}
OpCode::I64Extend8S => {
self.out.push(I64Extend8S);
}
OpCode::I64Extend16S => {
self.out.push(I64Extend16S);
}
OpCode::I64Extend32S => {
self.out.push(I64Extend32S);
}
}
Ok(())
}
Expand Down
2 changes: 2 additions & 0 deletions smart-contracts/wasm-transform/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,5 @@ pub mod validate;

#[cfg(test)]
mod metering_transformation_test;
#[cfg(test)]
mod tests;
5 changes: 5 additions & 0 deletions smart-contracts/wasm-transform/src/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1209,6 +1209,11 @@ impl<I: TryFromImport, R: RunnableCode> Artifact<I, R> {
// and then extend, making it so that it is extended with 0's.
top.long = unsafe { top.short } as u32 as i64;
}
InternalOpcode::I32Extend8S => unary_i32(&mut stack, |x| x as i8 as i32),
InternalOpcode::I32Extend16S => unary_i32(&mut stack, |x| x as i16 as i32),
InternalOpcode::I64Extend8S => unary_i64(&mut stack, |x| x as i8 as i64),
InternalOpcode::I64Extend16S => unary_i64(&mut stack, |x| x as i16 as i64),
InternalOpcode::I64Extend32S => unary_i64(&mut stack, |x| x as i32 as i64),
}
}

Expand Down
5 changes: 5 additions & 0 deletions smart-contracts/wasm-transform/src/metering_transformation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,11 @@ pub(crate) mod cost {
I32WrapI64 => SIMPLE_UNOP,
I64ExtendI32S => SIMPLE_UNOP,
I64ExtendI32U => SIMPLE_UNOP,
I32Extend8S => SIMPLE_UNOP,
I32Extend16S => SIMPLE_UNOP,
I64Extend8S => SIMPLE_UNOP,
I64Extend16S => SIMPLE_UNOP,
I64Extend32S => SIMPLE_UNOP,
};
Ok(res)
}
Expand Down
Loading

0 comments on commit 55f86ba

Please sign in to comment.