diff options
-rw-r--r-- | src/passes/GlobalStructInference.cpp | 6 | ||||
-rw-r--r-- | test/lit/passes/gsi.wast | 49 |
2 files changed, 53 insertions, 2 deletions
diff --git a/src/passes/GlobalStructInference.cpp b/src/passes/GlobalStructInference.cpp index 7526cdb76..4158db051 100644 --- a/src/passes/GlobalStructInference.cpp +++ b/src/passes/GlobalStructInference.cpp @@ -50,6 +50,7 @@ #include <variant> +#include "ir/bits.h" #include "ir/debuginfo.h" #include "ir/find_all.h" #include "ir/module-utils.h" @@ -421,8 +422,9 @@ struct GlobalStructInference : public Pass { Expression* ret; if (value.isConstant()) { // This is known to be a constant, so simply emit an expression for - // that constant. - ret = value.getConstant().makeExpression(wasm); + // that constant, and handle if the field is packed. + auto* expr = value.getConstant().makeExpression(wasm); + ret = Bits::makePackedFieldGet(expr, field, curr->signed_, wasm); } else { // Otherwise, this is non-constant, so we are in the situation where // we want to un-nest the value out of the struct.new it is in. Note diff --git a/test/lit/passes/gsi.wast b/test/lit/passes/gsi.wast index 57d8137f4..299b19e00 100644 --- a/test/lit/passes/gsi.wast +++ b/test/lit/passes/gsi.wast @@ -1895,3 +1895,52 @@ ) ) ) + +;; Test packed fields. +(module + ;; CHECK: (type $struct (struct (field i8))) + (type $struct (struct (field i8))) + + ;; CHECK: (type $1 (func (result i32))) + + ;; CHECK: (global $A (ref $struct) (struct.new $struct + ;; CHECK-NEXT: (i32.const 257) + ;; CHECK-NEXT: )) + (global $A (ref $struct) (struct.new $struct + (i32.const 257) + )) + + ;; CHECK: (global $B (ref $struct) (struct.new $struct + ;; CHECK-NEXT: (i32.const 258) + ;; CHECK-NEXT: )) + (global $B (ref $struct) (struct.new $struct + (i32.const 258) + )) + + ;; CHECK: (func $test (type $1) (result i32) + ;; CHECK-NEXT: (select + ;; CHECK-NEXT: (i32.and + ;; CHECK-NEXT: (i32.const 257) + ;; CHECK-NEXT: (i32.const 255) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.and + ;; CHECK-NEXT: (i32.const 258) + ;; CHECK-NEXT: (i32.const 255) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (ref.eq + ;; CHECK-NEXT: (ref.as_non_null + ;; CHECK-NEXT: (global.get $A) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (global.get $A) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $test (result i32) + ;; We can infer this value is one of two things since only two objects exist + ;; of this type. We must emit the proper truncated value for them, as the + ;; values are truncated into i8. + (struct.get_u $struct 0 + (global.get $A) + ) + ) +) |