Skip to content

Commit 0991ed3

Browse files
authored
Merge pull request bytecodealliance#41 from yurydelendik/threads
Adds threads operators support
2 parents 0573902 + 4c12a7a commit 0991ed3

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+413
-29
lines changed

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "wasmparser"
3-
version = "0.13.0"
3+
version = "0.14.0"
44
authors = ["Yury Delendik <[email protected]>"]
55
license = "Apache-2.0"
66
repository = "https://github.com/yurydelendik/wasmparser.rs"

src/parser.rs

+197-16
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ pub struct TableType {
130130
#[derive(Debug,Copy,Clone)]
131131
pub struct MemoryType {
132132
pub limits: ResizableLimits,
133+
pub shared: bool,
133134
}
134135

135136
#[derive(Debug,Copy,Clone)]
@@ -455,6 +456,11 @@ pub enum Operator<'a> {
455456
I64ReinterpretF64,
456457
F32ReinterpretI32,
457458
F64ReinterpretI64,
459+
I32Extend8S,
460+
I32Extend16S,
461+
I64Extend8S,
462+
I64Extend16S,
463+
I64Extend32S,
458464

459465
// 0xFC operators
460466
// Non-trapping Float-to-int Conversions
@@ -466,6 +472,75 @@ pub enum Operator<'a> {
466472
I64TruncUSatF32,
467473
I64TruncSSatF64,
468474
I64TruncUSatF64,
475+
476+
// 0xFE operators
477+
// https://github.com/WebAssembly/threads/blob/master/proposals/threads/Overview.md
478+
Wake { memarg: MemoryImmediate },
479+
I32Wait { memarg: MemoryImmediate },
480+
I64Wait { memarg: MemoryImmediate },
481+
I32AtomicLoad { memarg: MemoryImmediate },
482+
I64AtomicLoad { memarg: MemoryImmediate },
483+
I32AtomicLoad8U { memarg: MemoryImmediate },
484+
I32AtomicLoad16U { memarg: MemoryImmediate },
485+
I64AtomicLoad8U { memarg: MemoryImmediate },
486+
I64AtomicLoad16U { memarg: MemoryImmediate },
487+
I64AtomicLoad32U { memarg: MemoryImmediate },
488+
I32AtomicStore { memarg: MemoryImmediate },
489+
I64AtomicStore { memarg: MemoryImmediate },
490+
I32AtomicStore8 { memarg: MemoryImmediate },
491+
I32AtomicStore16 { memarg: MemoryImmediate },
492+
I64AtomicStore8 { memarg: MemoryImmediate },
493+
I64AtomicStore16 { memarg: MemoryImmediate },
494+
I64AtomicStore32 { memarg: MemoryImmediate },
495+
I32AtomicRmwAdd { memarg: MemoryImmediate },
496+
I64AtomicRmwAdd { memarg: MemoryImmediate },
497+
I32AtomicRmw8UAdd { memarg: MemoryImmediate },
498+
I32AtomicRmw16UAdd { memarg: MemoryImmediate },
499+
I64AtomicRmw8UAdd { memarg: MemoryImmediate },
500+
I64AtomicRmw16UAdd { memarg: MemoryImmediate },
501+
I64AtomicRmw32UAdd { memarg: MemoryImmediate },
502+
I32AtomicRmwSub { memarg: MemoryImmediate },
503+
I64AtomicRmwSub { memarg: MemoryImmediate },
504+
I32AtomicRmw8USub { memarg: MemoryImmediate },
505+
I32AtomicRmw16USub { memarg: MemoryImmediate },
506+
I64AtomicRmw8USub { memarg: MemoryImmediate },
507+
I64AtomicRmw16USub { memarg: MemoryImmediate },
508+
I64AtomicRmw32USub { memarg: MemoryImmediate },
509+
I32AtomicRmwAnd { memarg: MemoryImmediate },
510+
I64AtomicRmwAnd { memarg: MemoryImmediate },
511+
I32AtomicRmw8UAnd { memarg: MemoryImmediate },
512+
I32AtomicRmw16UAnd { memarg: MemoryImmediate },
513+
I64AtomicRmw8UAnd { memarg: MemoryImmediate },
514+
I64AtomicRmw16UAnd { memarg: MemoryImmediate },
515+
I64AtomicRmw32UAnd { memarg: MemoryImmediate },
516+
I32AtomicRmwOr { memarg: MemoryImmediate },
517+
I64AtomicRmwOr { memarg: MemoryImmediate },
518+
I32AtomicRmw8UOr { memarg: MemoryImmediate },
519+
I32AtomicRmw16UOr { memarg: MemoryImmediate },
520+
I64AtomicRmw8UOr { memarg: MemoryImmediate },
521+
I64AtomicRmw16UOr { memarg: MemoryImmediate },
522+
I64AtomicRmw32UOr { memarg: MemoryImmediate },
523+
I32AtomicRmwXor { memarg: MemoryImmediate },
524+
I64AtomicRmwXor { memarg: MemoryImmediate },
525+
I32AtomicRmw8UXor { memarg: MemoryImmediate },
526+
I32AtomicRmw16UXor { memarg: MemoryImmediate },
527+
I64AtomicRmw8UXor { memarg: MemoryImmediate },
528+
I64AtomicRmw16UXor { memarg: MemoryImmediate },
529+
I64AtomicRmw32UXor { memarg: MemoryImmediate },
530+
I32AtomicRmwXchg { memarg: MemoryImmediate },
531+
I64AtomicRmwXchg { memarg: MemoryImmediate },
532+
I32AtomicRmw8UXchg { memarg: MemoryImmediate },
533+
I32AtomicRmw16UXchg { memarg: MemoryImmediate },
534+
I64AtomicRmw8UXchg { memarg: MemoryImmediate },
535+
I64AtomicRmw16UXchg { memarg: MemoryImmediate },
536+
I64AtomicRmw32UXchg { memarg: MemoryImmediate },
537+
I32AtomicRmwCmpxchg { memarg: MemoryImmediate },
538+
I64AtomicRmwCmpxchg { memarg: MemoryImmediate },
539+
I32AtomicRmw8UCmpxchg { memarg: MemoryImmediate },
540+
I32AtomicRmw16UCmpxchg { memarg: MemoryImmediate },
541+
I64AtomicRmw8UCmpxchg { memarg: MemoryImmediate },
542+
I64AtomicRmw16UCmpxchg { memarg: MemoryImmediate },
543+
I64AtomicRmw32UCmpxchg { memarg: MemoryImmediate },
469544
}
470545

471546
fn is_name(name: &[u8], expected: &'static str) -> bool {
@@ -681,35 +756,43 @@ impl<'a> BinaryReader<'a> {
681756
})
682757
}
683758

684-
fn read_resizable_limits(&mut self) -> Result<ResizableLimits> {
685-
let flags = self.read_var_u32()?;
686-
if (flags & !0x1) != 0 {
687-
return Err(BinaryReaderError {
688-
message: "invalid resizable limits flags",
689-
offset: self.position - 1,
690-
});
691-
}
759+
fn read_resizable_limits(&mut self, max_present: bool) -> Result<ResizableLimits> {
692760
let initial = self.read_var_u32()?;
693-
let maximum = if (flags & 0x1) != 0 {
761+
let maximum = if max_present {
694762
Some(self.read_var_u32()?)
695763
} else {
696764
None
697765
};
698-
Ok(ResizableLimits {
699-
initial: initial,
700-
maximum: maximum,
701-
})
766+
Ok(ResizableLimits { initial, maximum })
702767
}
703768

704769
fn read_table_type(&mut self) -> Result<TableType> {
770+
let element_type = self.read_type()?;
771+
let flags = self.read_var_u32()?;
772+
if (flags & !0x1) != 0 {
773+
return Err(BinaryReaderError {
774+
message: "invalid table resizable limits flags",
775+
offset: self.position - 1,
776+
});
777+
}
778+
let limits = self.read_resizable_limits((flags & 0x1) != 0)?;
705779
Ok(TableType {
706-
element_type: self.read_type()?,
707-
limits: self.read_resizable_limits()?,
780+
element_type,
781+
limits,
708782
})
709783
}
710784

711785
fn read_memory_type(&mut self) -> Result<MemoryType> {
712-
Ok(MemoryType { limits: self.read_resizable_limits()? })
786+
let flags = self.read_var_u32()?;
787+
if (flags & !0x3) != 0 {
788+
return Err(BinaryReaderError {
789+
message: "invalid table resizable limits flags",
790+
offset: self.position - 1,
791+
});
792+
}
793+
let limits = self.read_resizable_limits((flags & 0x1) != 0)?;
794+
let shared = (flags & 0x2) != 0;
795+
Ok(MemoryType { limits, shared })
713796
}
714797

715798
fn read_global_type(&mut self) -> Result<GlobalType> {
@@ -961,6 +1044,96 @@ impl<'a> BinaryReader<'a> {
9611044
self.read_bytes(len)
9621045
}
9631046

1047+
fn read_memarg_of_align(&mut self, align: u32) -> Result<MemoryImmediate> {
1048+
let imm = self.read_memarg()?;
1049+
if align != imm.flags {
1050+
return Err(BinaryReaderError {
1051+
message: "Unexpected memarg alignment",
1052+
offset: self.position - 1,
1053+
});
1054+
}
1055+
Ok(imm)
1056+
}
1057+
1058+
fn read_0xfe_operator(&mut self) -> Result<Operator<'a>> {
1059+
let code = self.read_u8()? as u8;
1060+
Ok(match code {
1061+
0x00 => Operator::Wake { memarg: self.read_memarg_of_align(2)? },
1062+
0x01 => Operator::I32Wait { memarg: self.read_memarg_of_align(2)? },
1063+
0x02 => Operator::I64Wait { memarg: self.read_memarg_of_align(3)? },
1064+
0x10 => Operator::I32AtomicLoad { memarg: self.read_memarg_of_align(2)? },
1065+
0x11 => Operator::I64AtomicLoad { memarg: self.read_memarg_of_align(3)? },
1066+
0x12 => Operator::I32AtomicLoad8U { memarg: self.read_memarg_of_align(0)? },
1067+
0x13 => Operator::I32AtomicLoad16U { memarg: self.read_memarg_of_align(1)? },
1068+
0x14 => Operator::I64AtomicLoad8U { memarg: self.read_memarg_of_align(0)? },
1069+
0x15 => Operator::I64AtomicLoad16U { memarg: self.read_memarg_of_align(1)? },
1070+
0x16 => Operator::I64AtomicLoad32U { memarg: self.read_memarg_of_align(2)? },
1071+
0x17 => Operator::I32AtomicStore { memarg: self.read_memarg_of_align(2)? },
1072+
0x18 => Operator::I64AtomicStore { memarg: self.read_memarg_of_align(3)? },
1073+
0x19 => Operator::I32AtomicStore8 { memarg: self.read_memarg_of_align(0)? },
1074+
0x1a => Operator::I32AtomicStore16 { memarg: self.read_memarg_of_align(1)? },
1075+
0x1b => Operator::I64AtomicStore8 { memarg: self.read_memarg_of_align(0)? },
1076+
0x1c => Operator::I64AtomicStore16 { memarg: self.read_memarg_of_align(1)? },
1077+
0x1d => Operator::I64AtomicStore32 { memarg: self.read_memarg_of_align(2)? },
1078+
0x1e => Operator::I32AtomicRmwAdd { memarg: self.read_memarg_of_align(2)? },
1079+
0x1f => Operator::I64AtomicRmwAdd { memarg: self.read_memarg_of_align(3)? },
1080+
0x20 => Operator::I32AtomicRmw8UAdd { memarg: self.read_memarg_of_align(0)? },
1081+
0x21 => Operator::I32AtomicRmw16UAdd { memarg: self.read_memarg_of_align(1)? },
1082+
0x22 => Operator::I64AtomicRmw8UAdd { memarg: self.read_memarg_of_align(0)? },
1083+
0x23 => Operator::I64AtomicRmw16UAdd { memarg: self.read_memarg_of_align(1)? },
1084+
0x24 => Operator::I64AtomicRmw32UAdd { memarg: self.read_memarg_of_align(2)? },
1085+
0x25 => Operator::I32AtomicRmwSub { memarg: self.read_memarg_of_align(2)? },
1086+
0x26 => Operator::I64AtomicRmwSub { memarg: self.read_memarg_of_align(3)? },
1087+
0x27 => Operator::I32AtomicRmw8USub { memarg: self.read_memarg_of_align(0)? },
1088+
0x28 => Operator::I32AtomicRmw16USub { memarg: self.read_memarg_of_align(1)? },
1089+
0x29 => Operator::I64AtomicRmw8USub { memarg: self.read_memarg_of_align(0)? },
1090+
0x2a => Operator::I64AtomicRmw16USub { memarg: self.read_memarg_of_align(1)? },
1091+
0x2b => Operator::I64AtomicRmw32USub { memarg: self.read_memarg_of_align(2)? },
1092+
0x2c => Operator::I32AtomicRmwAnd { memarg: self.read_memarg_of_align(2)? },
1093+
0x2d => Operator::I64AtomicRmwAnd { memarg: self.read_memarg_of_align(3)? },
1094+
0x2e => Operator::I32AtomicRmw8UAnd { memarg: self.read_memarg_of_align(0)? },
1095+
0x2f => Operator::I32AtomicRmw16UAnd { memarg: self.read_memarg_of_align(1)? },
1096+
0x30 => Operator::I64AtomicRmw8UAnd { memarg: self.read_memarg_of_align(0)? },
1097+
0x31 => Operator::I64AtomicRmw16UAnd { memarg: self.read_memarg_of_align(1)? },
1098+
0x32 => Operator::I64AtomicRmw32UAnd { memarg: self.read_memarg_of_align(2)? },
1099+
0x33 => Operator::I32AtomicRmwOr { memarg: self.read_memarg_of_align(2)? },
1100+
0x34 => Operator::I64AtomicRmwOr { memarg: self.read_memarg_of_align(3)? },
1101+
0x35 => Operator::I32AtomicRmw8UOr { memarg: self.read_memarg_of_align(0)? },
1102+
0x36 => Operator::I32AtomicRmw16UOr { memarg: self.read_memarg_of_align(1)? },
1103+
0x37 => Operator::I64AtomicRmw8UOr { memarg: self.read_memarg_of_align(0)? },
1104+
0x38 => Operator::I64AtomicRmw16UOr { memarg: self.read_memarg_of_align(1)? },
1105+
0x39 => Operator::I64AtomicRmw32UOr { memarg: self.read_memarg_of_align(2)? },
1106+
0x3a => Operator::I32AtomicRmwXor { memarg: self.read_memarg_of_align(2)? },
1107+
0x3b => Operator::I64AtomicRmwXor { memarg: self.read_memarg_of_align(3)? },
1108+
0x3c => Operator::I32AtomicRmw8UXor { memarg: self.read_memarg_of_align(0)? },
1109+
0x3d => Operator::I32AtomicRmw16UXor { memarg: self.read_memarg_of_align(1)? },
1110+
0x3e => Operator::I64AtomicRmw8UXor { memarg: self.read_memarg_of_align(0)? },
1111+
0x3f => Operator::I64AtomicRmw16UXor { memarg: self.read_memarg_of_align(1)? },
1112+
0x40 => Operator::I64AtomicRmw32UXor { memarg: self.read_memarg_of_align(2)? },
1113+
0x41 => Operator::I32AtomicRmwXchg { memarg: self.read_memarg_of_align(2)? },
1114+
0x42 => Operator::I64AtomicRmwXchg { memarg: self.read_memarg_of_align(3)? },
1115+
0x43 => Operator::I32AtomicRmw8UXchg { memarg: self.read_memarg_of_align(0)? },
1116+
0x44 => Operator::I32AtomicRmw16UXchg { memarg: self.read_memarg_of_align(1)? },
1117+
0x45 => Operator::I64AtomicRmw8UXchg { memarg: self.read_memarg_of_align(0)? },
1118+
0x46 => Operator::I64AtomicRmw16UXchg { memarg: self.read_memarg_of_align(1)? },
1119+
0x47 => Operator::I64AtomicRmw32UXchg { memarg: self.read_memarg_of_align(2)? },
1120+
0x48 => Operator::I32AtomicRmwCmpxchg { memarg: self.read_memarg_of_align(2)? },
1121+
0x49 => Operator::I64AtomicRmwCmpxchg { memarg: self.read_memarg_of_align(3)? },
1122+
0x4a => Operator::I32AtomicRmw8UCmpxchg { memarg: self.read_memarg_of_align(0)? },
1123+
0x4b => Operator::I32AtomicRmw16UCmpxchg { memarg: self.read_memarg_of_align(1)? },
1124+
0x4c => Operator::I64AtomicRmw8UCmpxchg { memarg: self.read_memarg_of_align(0)? },
1125+
0x4d => Operator::I64AtomicRmw16UCmpxchg { memarg: self.read_memarg_of_align(1)? },
1126+
0x4e => Operator::I64AtomicRmw32UCmpxchg { memarg: self.read_memarg_of_align(2)? },
1127+
1128+
_ => {
1129+
return Err(BinaryReaderError {
1130+
message: "Unknown 0xFE opcode",
1131+
offset: self.position - 1,
1132+
})
1133+
}
1134+
})
1135+
}
1136+
9641137
pub fn read_operator(&mut self) -> Result<Operator<'a>> {
9651138
let code = self.read_u8()? as u8;
9661139
Ok(match code {
@@ -1142,8 +1315,16 @@ impl<'a> BinaryReader<'a> {
11421315
0xbe => Operator::F32ReinterpretI32,
11431316
0xbf => Operator::F64ReinterpretI64,
11441317

1318+
0xc0 => Operator::I32Extend8S,
1319+
0xc1 => Operator::I32Extend16S,
1320+
0xc2 => Operator::I64Extend8S,
1321+
0xc3 => Operator::I64Extend16S,
1322+
0xc4 => Operator::I64Extend32S,
1323+
11451324
0xfc => self.read_0xfc_operator()?,
11461325

1326+
0xfe => self.read_0xfe_operator()?,
1327+
11471328
_ => {
11481329
return Err(BinaryReaderError {
11491330
message: "Unknown opcode",

src/tests.rs

+8-3
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,12 @@ mod simple_tests {
1919
use std::fs::{File, read_dir};
2020
use std::path::PathBuf;
2121
use parser::{WasmDecoder, Parser, ParserState, ParserInput, SectionCode, Operator};
22-
use validator::ValidatingParser;
22+
use validator::{ValidatingParser, ValidatingParserConfig, OperatorValidatorConfig};
23+
24+
const VALIDATOR_CONFIG: Option<ValidatingParserConfig> =
25+
Some(ValidatingParserConfig {
26+
operator_config: OperatorValidatorConfig { enable_threads: true },
27+
});
2328

2429
fn read_file_data(path: &PathBuf) -> Vec<u8> {
2530
println!("Parsing {:?}", path);
@@ -62,7 +67,7 @@ mod simple_tests {
6267
continue;
6368
}
6469
let data = read_file_data(&dir.path());
65-
let mut parser = ValidatingParser::new(data.as_slice());
70+
let mut parser = ValidatingParser::new(data.as_slice(), VALIDATOR_CONFIG);
6671
let mut max_iteration = 100000000;
6772
loop {
6873
let state = parser.read();
@@ -87,7 +92,7 @@ mod simple_tests {
8792
continue;
8893
}
8994
let data = read_file_data(&dir.path());
90-
let mut parser = ValidatingParser::new(data.as_slice());
95+
let mut parser = ValidatingParser::new(data.as_slice(), VALIDATOR_CONFIG);
9196
let mut max_iteration = 100000000;
9297
let mut error = false;
9398
loop {

0 commit comments

Comments
 (0)