-
Notifications
You must be signed in to change notification settings - Fork 5
feat: add a 'records' example, and some required instructions #116
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
685351d
990022a
599000d
8544864
71140b1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -323,7 +323,7 @@ impl Bindgen for Func<'_> { | |
| let operand = &operands[0]; | ||
| quote_in! { self.body => | ||
| $['\r'] | ||
| $result := $WAZERO_API_DECODE_U32($operand) | ||
| $result := $WAZERO_API_DECODE_U32(uint64($operand)) | ||
| }; | ||
| results.push(Operand::SingleValue(result.into())); | ||
| } | ||
|
|
@@ -1087,16 +1087,168 @@ impl Bindgen for Func<'_> { | |
| Instruction::I32Load8S { .. } => todo!("implement instruction: {inst:?}"), | ||
| Instruction::I32Load16U { .. } => todo!("implement instruction: {inst:?}"), | ||
| Instruction::I32Load16S { .. } => todo!("implement instruction: {inst:?}"), | ||
| Instruction::I64Load { .. } => todo!("implement instruction: {inst:?}"), | ||
| Instruction::F32Load { .. } => todo!("implement instruction: {inst:?}"), | ||
| Instruction::F64Load { .. } => todo!("implement instruction: {inst:?}"), | ||
| Instruction::I64Load { offset } => { | ||
| // TODO(#58): Support additional ArchitectureSize | ||
| let offset = offset.size_wasm32(); | ||
| let tmp = self.tmp(); | ||
| let value = &format!("value{tmp}"); | ||
| let ok = &format!("ok{tmp}"); | ||
| let default = &format!("default{tmp}"); | ||
| let operand = &operands[0]; | ||
| quote_in! { self.body => | ||
| $['\r'] | ||
| $value, $ok := i.module.Memory().ReadUint64Le(uint32($operand + $offset)) | ||
| $(match &self.result { | ||
| GoResult::Anon(GoType::ValueOrError(typ)) => { | ||
| if !$ok { | ||
| var $default $(typ.as_ref()) | ||
| return $default, $ERRORS_NEW("failed to read i64 from memory") | ||
| } | ||
| } | ||
| GoResult::Anon(GoType::Error) => { | ||
| if !$ok { | ||
| return $ERRORS_NEW("failed to read i64 from memory") | ||
| } | ||
| } | ||
| GoResult::Anon(_) | GoResult::Empty => { | ||
| $(comment(&["The return type doesn't contain an error so we panic if one is encountered"])) | ||
| if !$ok { | ||
| panic($ERRORS_NEW("failed to read i64 from memory")) | ||
| } | ||
| } | ||
| }) | ||
| }; | ||
| results.push(Operand::SingleValue(value.into())); | ||
| } | ||
| Instruction::F32Load { offset } => { | ||
| // TODO(#58): Support additional ArchitectureSize | ||
| let offset = offset.size_wasm32(); | ||
| let tmp = self.tmp(); | ||
| let value = &format!("value{tmp}"); | ||
| let ok = &format!("ok{tmp}"); | ||
| let default = &format!("default{tmp}"); | ||
| let operand = &operands[0]; | ||
| quote_in! { self.body => | ||
| $['\r'] | ||
| $value, $ok := i.module.Memory().ReadUint64Le(uint32($operand + $offset)) | ||
| $(match &self.result { | ||
| GoResult::Anon(GoType::ValueOrError(typ)) => { | ||
| if !$ok { | ||
| var $default $(typ.as_ref()) | ||
| return $default, $ERRORS_NEW("failed to read f32 from memory") | ||
| } | ||
| } | ||
| GoResult::Anon(GoType::Error) => { | ||
| if !$ok { | ||
| return $ERRORS_NEW("failed to read f32 from memory") | ||
| } | ||
| } | ||
| GoResult::Anon(_) | GoResult::Empty => { | ||
| $(comment(&["The return type doesn't contain an error so we panic if one is encountered"])) | ||
| if !$ok { | ||
| panic($ERRORS_NEW("failed to read f32 from memory")) | ||
| } | ||
| } | ||
| }) | ||
| }; | ||
| results.push(Operand::SingleValue(value.into())); | ||
| } | ||
| Instruction::F64Load { offset } => { | ||
| // TODO(#58): Support additional ArchitectureSize | ||
| let offset = offset.size_wasm32(); | ||
| let tmp = self.tmp(); | ||
| let value = &format!("value{tmp}"); | ||
| let ok = &format!("ok{tmp}"); | ||
| let default = &format!("default{tmp}"); | ||
| let operand = &operands[0]; | ||
| quote_in! { self.body => | ||
| $['\r'] | ||
| $value, $ok := i.module.Memory().ReadUint64Le(uint32($operand + $offset)) | ||
| $(match &self.result { | ||
| GoResult::Anon(GoType::ValueOrError(typ)) => { | ||
| if !$ok { | ||
| var $default $(typ.as_ref()) | ||
| return $default, $ERRORS_NEW("failed to read f64 from memory") | ||
| } | ||
| } | ||
| GoResult::Anon(GoType::Error) => { | ||
| if !$ok { | ||
| return $ERRORS_NEW("failed to read f64 from memory") | ||
| } | ||
| } | ||
| GoResult::Anon(_) | GoResult::Empty => { | ||
| $(comment(&["The return type doesn't contain an error so we panic if one is encountered"])) | ||
| if !$ok { | ||
| panic($ERRORS_NEW("failed to read f64 from memory")) | ||
| } | ||
| } | ||
| }) | ||
| }; | ||
| results.push(Operand::SingleValue(value.into())); | ||
| } | ||
| Instruction::I32Store16 { .. } => todo!("implement instruction: {inst:?}"), | ||
| Instruction::I64Store { .. } => todo!("implement instruction: {inst:?}"), | ||
| Instruction::F32Store { .. } => todo!("implement instruction: {inst:?}"), | ||
| Instruction::F64Store { .. } => todo!("implement instruction: {inst:?}"), | ||
| Instruction::F32Store { offset } => { | ||
| // TODO(#58): Support additional ArchitectureSize | ||
| let offset = offset.size_wasm32(); | ||
| let tag = &operands[0]; | ||
| let ptr = &operands[1]; | ||
| match &self.direction { | ||
| Direction::Export => { | ||
| quote_in! { self.body => | ||
| $['\r'] | ||
| i.module.Memory().WriteUint64Le($ptr+$offset, $tag) | ||
| } | ||
| } | ||
| Direction::Import { .. } => { | ||
| quote_in! { self.body => | ||
| $['\r'] | ||
| mod.Memory().WriteUint64Le($ptr+$offset, $tag) | ||
| } | ||
| } | ||
| } | ||
| } | ||
| Instruction::F64Store { offset } => { | ||
| // TODO(#58): Support additional ArchitectureSize | ||
| let offset = offset.size_wasm32(); | ||
| let tag = &operands[0]; | ||
| let ptr = &operands[1]; | ||
| match &self.direction { | ||
| Direction::Export => { | ||
| quote_in! { self.body => | ||
| $['\r'] | ||
| i.module.Memory().WriteUint64Le($ptr+$offset, $tag) | ||
| } | ||
| } | ||
| Direction::Import { .. } => { | ||
| quote_in! { self.body => | ||
| $['\r'] | ||
| mod.Memory().WriteUint64Le($ptr+$offset, $tag) | ||
| } | ||
| } | ||
| } | ||
| } | ||
| Instruction::I32FromChar => todo!("implement instruction: {inst:?}"), | ||
| Instruction::I64FromU64 => todo!("implement instruction: {inst:?}"), | ||
| Instruction::I64FromS64 => todo!("implement instruction: {inst:?}"), | ||
| Instruction::I64FromU64 => { | ||
| let tmp = self.tmp(); | ||
| let value = format!("value{tmp}"); | ||
| let operand = &operands[0]; | ||
| quote_in! { self.body => | ||
| $['\r'] | ||
| $(&value) := int64($operand) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there a Wazero utility for this since a U64 could wrap in an I64?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not that I can see 😕 from what I can tell the behaviour is correct though and follows two's complement behaviour that both Go and Wasm expect. |
||
| } | ||
| results.push(Operand::SingleValue(value.into())); | ||
| } | ||
| Instruction::I64FromS64 => { | ||
| let tmp = self.tmp(); | ||
| let value = format!("value{tmp}"); | ||
| let operand = &operands[0]; | ||
| quote_in! { self.body => | ||
| $['\r'] | ||
| $(&value) := $operand | ||
| } | ||
| results.push(Operand::SingleValue(value.into())); | ||
| } | ||
| Instruction::I32FromS32 => { | ||
| let tmp = self.tmp(); | ||
| let value = format!("value{tmp}"); | ||
|
|
@@ -1196,7 +1348,16 @@ impl Bindgen for Func<'_> { | |
| results.push(Operand::SingleValue(result.into())); | ||
| } | ||
| Instruction::S64FromI64 => todo!("implement instruction: {inst:?}"), | ||
| Instruction::U64FromI64 => todo!("implement instruction: {inst:?}"), | ||
| Instruction::U64FromI64 => { | ||
| let tmp = self.tmp(); | ||
| let value = format!("value{tmp}"); | ||
| let operand = &operands[0]; | ||
| quote_in! { self.body => | ||
| $['\r'] | ||
| $(&value) := uint64($operand) | ||
| } | ||
| results.push(Operand::SingleValue(value.into())); | ||
| } | ||
| Instruction::CharFromI32 => todo!("implement instruction: {inst:?}"), | ||
| Instruction::F32FromCoreF32 => { | ||
| let tmp = self.tmp(); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This may look weird but
operandcan sometimes be auint32now, if thisU32FromI32instruction is called after aPointerLoad, as happens in records, which callsReadUint32Le. SinceDecodeU32requires the arg to be a uint64, we have to explicitly cast, which should be a no-op since the u32 always fits in the u64.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've actually encountered this today and it is a bigger problem than just this fix. I think all of the read/writes need to be converted to the uint64 variant but that large of a change is going to need validation.