@@ -113,6 +113,11 @@ def_instruction! {
113
113
/// it, using the specified constant offset.
114
114
F64Load { offset: i32 } : [ 1 ] => [ 1 ] ,
115
115
116
+ /// Like `I32Load` or `I64Load`, but for loading pointer values.
117
+ PointerLoad { offset: i32 } : [ 1 ] => [ 1 ] ,
118
+ /// Like `I32Load` or `I64Load`, but for loading array length values.
119
+ LengthLoad { offset: i32 } : [ 1 ] => [ 1 ] ,
120
+
116
121
/// Pops an `i32` address from the stack and then an `i32` value.
117
122
/// Stores the value in little-endian at the pointer specified plus the
118
123
/// constant `offset`.
@@ -138,6 +143,11 @@ def_instruction! {
138
143
/// constant `offset`.
139
144
F64Store { offset: i32 } : [ 2 ] => [ 0 ] ,
140
145
146
+ /// Like `I32Store` or `I64Store`, but for storing pointer values.
147
+ PointerStore { offset: i32 } : [ 2 ] => [ 0 ] ,
148
+ /// Like `I32Store` or `I64Store`, but for storing array length values.
149
+ LengthStore { offset: i32 } : [ 2 ] => [ 0 ] ,
150
+
141
151
// Scalar lifting/lowering
142
152
143
153
/// Converts an interface type `char` value to a 32-bit integer
@@ -526,6 +536,24 @@ pub enum Bitcast {
526
536
I64ToI32 ,
527
537
I64ToF32 ,
528
538
539
+ // PointerOrI64<->Pointer conversions. These preserve provenance.
540
+ //
541
+ // These are used when pointer values are being stored in
542
+ // (PToP64) and loaded out of (P64ToP) PointerOrI64 values, so they
543
+ // always have to preserve provenance.
544
+ P64ToP ,
545
+ PToP64 ,
546
+
547
+ // Pointer<->integer conversions. These do not preserve provenance.
548
+ //
549
+ // These are used when integer values are being stored in
550
+ // (I64ToP64 and I32ToP) and loaded out of (P64ToI64 and PToI32) pointer
551
+ // or PointerOrI64 values, so they never have any provenance to preserve.
552
+ P64ToI64 ,
553
+ I64ToP64 ,
554
+ I32ToP ,
555
+ PToI32 ,
556
+
529
557
None ,
530
558
}
531
559
@@ -1517,9 +1545,9 @@ impl<'a, B: Bindgen> Generator<'a, B> {
1517
1545
// and the length into the high address.
1518
1546
self . lower ( ty) ;
1519
1547
self . stack . push ( addr. clone ( ) ) ;
1520
- self . emit ( & Instruction :: I32Store { offset : offset + 4 } ) ;
1548
+ self . emit ( & Instruction :: LengthStore { offset : offset + 4 } ) ;
1521
1549
self . stack . push ( addr) ;
1522
- self . emit ( & Instruction :: I32Store { offset } ) ;
1550
+ self . emit ( & Instruction :: PointerStore { offset } ) ;
1523
1551
}
1524
1552
1525
1553
fn write_fields_to_memory < ' b > (
@@ -1689,9 +1717,9 @@ impl<'a, B: Bindgen> Generator<'a, B> {
1689
1717
// Read the pointer/len and then perform the standard lifting
1690
1718
// proceses.
1691
1719
self . stack . push ( addr. clone ( ) ) ;
1692
- self . emit ( & Instruction :: I32Load { offset } ) ;
1720
+ self . emit ( & Instruction :: PointerLoad { offset } ) ;
1693
1721
self . stack . push ( addr) ;
1694
- self . emit ( & Instruction :: I32Load { offset : offset + 4 } ) ;
1722
+ self . emit ( & Instruction :: LengthLoad { offset : offset + 4 } ) ;
1695
1723
self . lift ( ty) ;
1696
1724
}
1697
1725
@@ -1742,9 +1770,9 @@ impl<'a, B: Bindgen> Generator<'a, B> {
1742
1770
match * ty {
1743
1771
Type :: String => {
1744
1772
self . stack . push ( addr. clone ( ) ) ;
1745
- self . emit ( & Instruction :: I32Load { offset } ) ;
1773
+ self . emit ( & Instruction :: PointerLoad { offset } ) ;
1746
1774
self . stack . push ( addr) ;
1747
- self . emit ( & Instruction :: I32Load { offset : offset + 4 } ) ;
1775
+ self . emit ( & Instruction :: LengthLoad { offset : offset + 4 } ) ;
1748
1776
self . emit ( & Instruction :: GuestDeallocateString ) ;
1749
1777
}
1750
1778
@@ -1772,9 +1800,9 @@ impl<'a, B: Bindgen> Generator<'a, B> {
1772
1800
self . finish_block ( 0 ) ;
1773
1801
1774
1802
self . stack . push ( addr. clone ( ) ) ;
1775
- self . emit ( & Instruction :: I32Load { offset } ) ;
1803
+ self . emit ( & Instruction :: PointerLoad { offset } ) ;
1776
1804
self . stack . push ( addr) ;
1777
- self . emit ( & Instruction :: I32Load { offset : offset + 4 } ) ;
1805
+ self . emit ( & Instruction :: LengthLoad { offset : offset + 4 } ) ;
1778
1806
self . emit ( & Instruction :: GuestDeallocateList { element } ) ;
1779
1807
}
1780
1808
@@ -1862,7 +1890,12 @@ fn cast(from: WasmType, to: WasmType) -> Bitcast {
1862
1890
use WasmType :: * ;
1863
1891
1864
1892
match ( from, to) {
1865
- ( I32 , I32 ) | ( I64 , I64 ) | ( F32 , F32 ) | ( F64 , F64 ) => Bitcast :: None ,
1893
+ ( I32 , I32 )
1894
+ | ( I64 , I64 )
1895
+ | ( F32 , F32 )
1896
+ | ( F64 , F64 )
1897
+ | ( Pointer , Pointer )
1898
+ | ( Length , Length ) => Bitcast :: None ,
1866
1899
1867
1900
( I32 , I64 ) => Bitcast :: I32ToI64 ,
1868
1901
( F32 , I32 ) => Bitcast :: F32ToI32 ,
@@ -1875,7 +1908,22 @@ fn cast(from: WasmType, to: WasmType) -> Bitcast {
1875
1908
( F32 , I64 ) => Bitcast :: F32ToI64 ,
1876
1909
( I64 , F32 ) => Bitcast :: I64ToF32 ,
1877
1910
1878
- ( F32 , F64 ) | ( F64 , F32 ) | ( F64 , I32 ) | ( I32 , F64 ) => unreachable ! ( ) ,
1911
+ ( I64 , PointerOrI64 ) => Bitcast :: I64ToP64 ,
1912
+ ( PointerOrI64 , I64 ) => Bitcast :: P64ToI64 ,
1913
+ ( Pointer , PointerOrI64 ) => Bitcast :: PToP64 ,
1914
+ ( PointerOrI64 , Pointer ) => Bitcast :: P64ToP ,
1915
+
1916
+ ( I32 , Pointer ) => Bitcast :: I32ToP ,
1917
+ ( Pointer , I32 ) => Bitcast :: PToI32 ,
1918
+
1919
+ ( Pointer | PointerOrI64 | Length , _)
1920
+ | ( _, Pointer | PointerOrI64 | Length )
1921
+ | ( F32 , F64 )
1922
+ | ( F64 , F32 )
1923
+ | ( F64 , I32 )
1924
+ | ( I32 , F64 ) => {
1925
+ unreachable ! ( "Don't know how to bitcast from {:?} to {:?}" , from, to) ;
1926
+ }
1879
1927
}
1880
1928
}
1881
1929
0 commit comments