Skip to content

Commit 3cf4e19

Browse files
alexcrichtonsunfishcode
authored andcommitted
Embed type-hint declarations in AST payloads
Instead of having a separate variant for `Char8` and `Usize` instead store boolean flags on `U8` and `U32` whether they're intended for these language-specific purposes. This additionally changes to require `@witx` when parsing `char8` to ensure usage is flagged as witx-specific.
1 parent b07d794 commit 3cf4e19

16 files changed

+102
-67
lines changed

phases/ephemeral/docs.md

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Types
2-
## <a href="#size" name="size"></a> `size`: `usize`
2+
## <a href="#size" name="size"></a> `size`: `u32`
33
An array size.
44

55
Note: This is similar to `size_t` in POSIX.
@@ -1097,14 +1097,14 @@ When type is [`preopentype::dir`](#preopentype.dir):
10971097

10981098
---
10991099

1100-
#### <a href="#get" name="get"></a> `get(argv: Pointer<Pointer<char8>>, argv_buf: Pointer<char8>) -> errno`
1100+
#### <a href="#get" name="get"></a> `get(argv: Pointer<Pointer<u8>>, argv_buf: Pointer<u8>) -> errno`
11011101
Read command-line argument data.
11021102
The size of the array should match that returned by [`sizes_get`](#sizes_get)
11031103

11041104
##### Params
1105-
- <a href="#get.argv" name="get.argv"></a> `argv`: `Pointer<Pointer<char8>>`
1105+
- <a href="#get.argv" name="get.argv"></a> `argv`: `Pointer<Pointer<u8>>`
11061106

1107-
- <a href="#get.argv_buf" name="get.argv_buf"></a> `argv_buf`: `Pointer<char8>`
1107+
- <a href="#get.argv_buf" name="get.argv_buf"></a> `argv_buf`: `Pointer<u8>`
11081108

11091109
##### Results
11101110
- <a href="#get.error" name="get.error"></a> `error`: [`errno`](#errno)
@@ -1175,14 +1175,14 @@ The time value of the clock.
11751175

11761176
---
11771177

1178-
#### <a href="#get" name="get"></a> `get(environ: Pointer<Pointer<char8>>, environ_buf: Pointer<char8>) -> errno`
1178+
#### <a href="#get" name="get"></a> `get(environ: Pointer<Pointer<u8>>, environ_buf: Pointer<u8>) -> errno`
11791179
Read environment variable data.
11801180
The sizes of the buffers should match that returned by [`sizes_get`](#sizes_get).
11811181

11821182
##### Params
1183-
- <a href="#get.environ" name="get.environ"></a> `environ`: `Pointer<Pointer<char8>>`
1183+
- <a href="#get.environ" name="get.environ"></a> `environ`: `Pointer<Pointer<u8>>`
11841184

1185-
- <a href="#get.environ_buf" name="get.environ_buf"></a> `environ_buf`: `Pointer<char8>`
1185+
- <a href="#get.environ_buf" name="get.environ_buf"></a> `environ_buf`: `Pointer<u8>`
11861186

11871187
##### Results
11881188
- <a href="#get.error" name="get.error"></a> `error`: [`errno`](#errno)
@@ -1443,13 +1443,13 @@ The buffer where the description is stored.
14431443

14441444
---
14451445

1446-
#### <a href="#prestat_dir_name" name="prestat_dir_name"></a> `prestat_dir_name(fd: fd, path: Pointer<char8>, path_len: size) -> errno`
1446+
#### <a href="#prestat_dir_name" name="prestat_dir_name"></a> `prestat_dir_name(fd: fd, path: Pointer<u8>, path_len: size) -> errno`
14471447
Return a description of the given preopened file descriptor.
14481448

14491449
##### Params
14501450
- <a href="#prestat_dir_name.fd" name="prestat_dir_name.fd"></a> `fd`: [`fd`](#fd)
14511451

1452-
- <a href="#prestat_dir_name.path" name="prestat_dir_name.path"></a> `path`: `Pointer<char8>`
1452+
- <a href="#prestat_dir_name.path" name="prestat_dir_name.path"></a> `path`: `Pointer<u8>`
14531453
A buffer into which to write the preopened directory name.
14541454

14551455
- <a href="#prestat_dir_name.path_len" name="prestat_dir_name.path_len"></a> `path_len`: [`size`](#size)
@@ -1806,7 +1806,7 @@ The file descriptor of the file that has been opened.
18061806

18071807
---
18081808

1809-
#### <a href="#readlink" name="readlink"></a> `readlink(fd: fd, path: string, buf: Pointer<char8>, buf_len: size) -> (errno, size)`
1809+
#### <a href="#readlink" name="readlink"></a> `readlink(fd: fd, path: string, buf: Pointer<u8>, buf_len: size) -> (errno, size)`
18101810
Read the contents of a symbolic link.
18111811
Note: This is similar to `readlinkat` in POSIX.
18121812

@@ -1816,7 +1816,7 @@ Note: This is similar to `readlinkat` in POSIX.
18161816
- <a href="#readlink.path" name="readlink.path"></a> `path`: `string`
18171817
The path of the symbolic link from which to read.
18181818

1819-
- <a href="#readlink.buf" name="readlink.buf"></a> `buf`: `Pointer<char8>`
1819+
- <a href="#readlink.buf" name="readlink.buf"></a> `buf`: `Pointer<u8>`
18201820
The buffer to which to write the contents of the symbolic link.
18211821

18221822
- <a href="#readlink.buf_len" name="readlink.buf_len"></a> `buf_len`: [`size`](#size)

phases/ephemeral/witx/wasi_ephemeral_args.witx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212
;;; Read command-line argument data.
1313
;;; The size of the array should match that returned by `sizes_get`
1414
(@interface func (export "get")
15-
(param $argv (@witx pointer (@witx pointer char8)))
16-
(param $argv_buf (@witx pointer char8))
15+
(param $argv (@witx pointer (@witx pointer (@witx char8))))
16+
(param $argv_buf (@witx pointer (@witx char8)))
1717
(result $error $errno)
1818
)
1919

phases/ephemeral/witx/wasi_ephemeral_environ.witx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212
;;; Read environment variable data.
1313
;;; The sizes of the buffers should match that returned by `sizes_get`.
1414
(@interface func (export "get")
15-
(param $environ (@witx pointer (@witx pointer char8)))
16-
(param $environ_buf (@witx pointer char8))
15+
(param $environ (@witx pointer (@witx pointer (@witx char8))))
16+
(param $environ_buf (@witx pointer (@witx char8)))
1717
(result $error $errno)
1818
)
1919

phases/ephemeral/witx/wasi_ephemeral_fd.witx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@
151151
(@interface func (export "prestat_dir_name")
152152
(param $fd $fd)
153153
;;; A buffer into which to write the preopened directory name.
154-
(param $path (@witx pointer char8))
154+
(param $path (@witx pointer (@witx char8)))
155155
(param $path_len $size)
156156
(result $error $errno)
157157
)

phases/ephemeral/witx/wasi_ephemeral_path.witx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@
131131
;;; The path of the symbolic link from which to read.
132132
(param $path string)
133133
;;; The buffer to which to write the contents of the symbolic link.
134-
(param $buf (@witx pointer char8))
134+
(param $buf (@witx pointer (@witx char8)))
135135
(param $buf_len $size)
136136
(result $error $errno)
137137
;;; The number of bytes placed in the buffer.

tools/witx/src/ast.rs

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -211,12 +211,27 @@ impl Type {
211211

212212
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
213213
pub enum BuiltinType {
214-
Char8,
215214
Char,
216-
USize,
217-
U8,
215+
U8 {
216+
/// Indicates whether this type is intended to represent the `char`
217+
/// type in the C language. The C `char` type is often unsigned, but
218+
/// it's language-specific. At an interface-types level this is an
219+
/// unsigned byte but binding generators may wish to bind this as the
220+
/// language-specific representation for a C character instead.
221+
lang_c_char: bool,
222+
},
218223
U16,
219-
U32,
224+
U32 {
225+
/// Indicates that this 32-bit value should actually be considered a
226+
/// pointer-like value in language bindings. At the interface types
227+
/// layer this is always a 32-bit unsigned value, but binding
228+
/// generators may wish to instead bind this as the equivalent of C's
229+
/// `size_t` for convenience with other APIs.
230+
///
231+
/// This allows witx authors to communicate the intent that the
232+
/// argument or return-value is pointer-like.
233+
lang_ptr_size: bool,
234+
},
220235
U64,
221236
S8,
222237
S16,
@@ -237,9 +252,11 @@ pub enum IntRepr {
237252
impl IntRepr {
238253
pub fn to_builtin(&self) -> BuiltinType {
239254
match self {
240-
IntRepr::U8 => BuiltinType::U8,
255+
IntRepr::U8 => BuiltinType::U8 { lang_c_char: false },
241256
IntRepr::U16 => BuiltinType::U16,
242-
IntRepr::U32 => BuiltinType::U32,
257+
IntRepr::U32 => BuiltinType::U32 {
258+
lang_ptr_size: false,
259+
},
243260
IntRepr::U64 => BuiltinType::U64,
244261
}
245262
}

tools/witx/src/coretypes.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,13 @@ impl Type {
3535
pub fn passed_by(&self) -> TypePassedBy {
3636
match self {
3737
Type::Builtin(b) => match b {
38-
BuiltinType::U8
38+
BuiltinType::U8 { .. }
3939
| BuiltinType::U16
40-
| BuiltinType::U32
40+
| BuiltinType::U32 { .. }
4141
| BuiltinType::S8
4242
| BuiltinType::S16
4343
| BuiltinType::S32
44-
| BuiltinType::Char8
45-
| BuiltinType::Char
46-
| BuiltinType::USize => TypePassedBy::Value(AtomType::I32),
44+
| BuiltinType::Char => TypePassedBy::Value(AtomType::I32),
4745
BuiltinType::U64 | BuiltinType::S64 => TypePassedBy::Value(AtomType::I64),
4846
BuiltinType::F32 => TypePassedBy::Value(AtomType::F32),
4947
BuiltinType::F64 => TypePassedBy::Value(AtomType::F64),

tools/witx/src/docs/ast.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -288,12 +288,10 @@ impl ToMarkdown for InterfaceFuncParam {
288288
impl BuiltinType {
289289
pub fn type_name(&self) -> &'static str {
290290
match self {
291-
BuiltinType::Char8 => "char8",
292291
BuiltinType::Char => "char",
293-
BuiltinType::USize => "usize",
294-
BuiltinType::U8 => "u8",
292+
BuiltinType::U8 { .. } => "u8",
295293
BuiltinType::U16 => "u16",
296-
BuiltinType::U32 => "u32",
294+
BuiltinType::U32 { .. } => "u32",
297295
BuiltinType::U64 => "u64",
298296
BuiltinType::S8 => "s8",
299297
BuiltinType::S16 => "s16",

tools/witx/src/layout.rs

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ impl Type {
6868
Type::Variant(s) => s.mem_size_align(),
6969
Type::Handle(h) => h.mem_size_align(),
7070
Type::List { .. } => SizeAlign { size: 8, align: 4 }, // Pointer and Length
71-
Type::Pointer { .. } | Type::ConstPointer { .. } => BuiltinType::U32.mem_size_align(),
71+
Type::Pointer { .. } | Type::ConstPointer { .. } => BuiltinType::S32.mem_size_align(),
7272
Type::Builtin(b) => b.mem_size_align(),
7373
}
7474
}
@@ -179,22 +179,18 @@ mod test {
179179

180180
impl Layout for HandleDatatype {
181181
fn mem_size_align(&self) -> SizeAlign {
182-
BuiltinType::U32.mem_size_align()
182+
BuiltinType::S32.mem_size_align()
183183
}
184184
}
185185

186186
impl Layout for BuiltinType {
187187
fn mem_size_align(&self) -> SizeAlign {
188188
match self {
189-
BuiltinType::U8 | BuiltinType::S8 | BuiltinType::Char8 => {
190-
SizeAlign { size: 1, align: 1 }
191-
}
189+
BuiltinType::U8 { .. } | BuiltinType::S8 => SizeAlign { size: 1, align: 1 },
192190
BuiltinType::U16 | BuiltinType::S16 => SizeAlign { size: 2, align: 2 },
193-
BuiltinType::Char
194-
| BuiltinType::USize
195-
| BuiltinType::U32
196-
| BuiltinType::S32
197-
| BuiltinType::F32 => SizeAlign { size: 4, align: 4 },
191+
BuiltinType::Char | BuiltinType::U32 { .. } | BuiltinType::S32 | BuiltinType::F32 => {
192+
SizeAlign { size: 4, align: 4 }
193+
}
198194
BuiltinType::U64 | BuiltinType::S64 | BuiltinType::F64 => {
199195
SizeAlign { size: 8, align: 8 }
200196
}

tools/witx/src/parser.rs

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -60,21 +60,20 @@ mod annotation {
6060
impl Parse<'_> for BuiltinType {
6161
fn parse(parser: Parser<'_>) -> Result<Self> {
6262
let mut l = parser.lookahead1();
63-
if l.peek::<kw::char8>() {
64-
parser.parse::<kw::char8>()?;
65-
Ok(BuiltinType::Char8)
66-
} else if l.peek::<kw::char>() {
63+
if l.peek::<kw::char>() {
6764
parser.parse::<kw::char>()?;
6865
Ok(BuiltinType::Char)
6966
} else if l.peek::<kw::u8>() {
7067
parser.parse::<kw::u8>()?;
71-
Ok(BuiltinType::U8)
68+
Ok(BuiltinType::U8 { lang_c_char: false })
7269
} else if l.peek::<kw::u16>() {
7370
parser.parse::<kw::u16>()?;
7471
Ok(BuiltinType::U16)
7572
} else if l.peek::<kw::u32>() {
7673
parser.parse::<kw::u32>()?;
77-
Ok(BuiltinType::U32)
74+
Ok(BuiltinType::U32 {
75+
lang_ptr_size: false,
76+
})
7877
} else if l.peek::<kw::u64>() {
7978
parser.parse::<kw::u64>()?;
8079
Ok(BuiltinType::U64)
@@ -104,8 +103,7 @@ impl Parse<'_> for BuiltinType {
104103

105104
impl wast::parser::Peek for BuiltinType {
106105
fn peek(cursor: wast::parser::Cursor<'_>) -> bool {
107-
<kw::char8 as Peek>::peek(cursor)
108-
|| <kw::char as Peek>::peek(cursor)
106+
<kw::char as Peek>::peek(cursor)
109107
|| <kw::u8 as Peek>::peek(cursor)
110108
|| <kw::u16 as Peek>::peek(cursor)
111109
|| <kw::u32 as Peek>::peek(cursor)
@@ -331,7 +329,14 @@ impl<'a> Parse<'a> for TypedefSyntax<'a> {
331329
Ok(TypedefSyntax::Pointer(Box::new(parser.parse()?)))
332330
} else if l.peek::<kw::usize>() {
333331
parser.parse::<kw::usize>()?;
334-
Ok(TypedefSyntax::Builtin(BuiltinType::USize))
332+
Ok(TypedefSyntax::Builtin(BuiltinType::U32 {
333+
lang_ptr_size: true,
334+
}))
335+
} else if l.peek::<kw::char8>() {
336+
parser.parse::<kw::char8>()?;
337+
Ok(TypedefSyntax::Builtin(BuiltinType::U8 {
338+
lang_c_char: true,
339+
}))
335340
} else {
336341
Err(l.error())
337342
}

tools/witx/src/render.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,12 +77,18 @@ impl Id {
7777
impl BuiltinType {
7878
pub fn to_sexpr(&self) -> SExpr {
7979
match self {
80-
BuiltinType::Char8 => SExpr::word("char8"),
8180
BuiltinType::Char => SExpr::word("char"),
82-
BuiltinType::USize => SExpr::Vec(vec![SExpr::annot("witx"), SExpr::word("usize")]),
83-
BuiltinType::U8 => SExpr::word("u8"),
81+
BuiltinType::U8 { lang_c_char: true } => {
82+
SExpr::Vec(vec![SExpr::annot("witx"), SExpr::word("char8")])
83+
}
84+
BuiltinType::U8 { lang_c_char: false } => SExpr::word("u8"),
8485
BuiltinType::U16 => SExpr::word("u16"),
85-
BuiltinType::U32 => SExpr::word("u32"),
86+
BuiltinType::U32 {
87+
lang_ptr_size: false,
88+
} => SExpr::word("u32"),
89+
BuiltinType::U32 {
90+
lang_ptr_size: true,
91+
} => SExpr::Vec(vec![SExpr::annot("witx"), SExpr::word("usize")]),
8692
BuiltinType::U64 => SExpr::word("u64"),
8793
BuiltinType::S8 => SExpr::word("s8"),
8894
BuiltinType::S16 => SExpr::word("s16"),

tools/witx/src/representation.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,17 @@ impl Representable for BuiltinType {
3030
return RepEquality::Eq;
3131
}
3232
match self {
33-
BuiltinType::U8 => match by {
34-
BuiltinType::U64 | BuiltinType::U32 | BuiltinType::U16 => RepEquality::Superset,
33+
BuiltinType::U8 { .. } => match by {
34+
BuiltinType::U64 | BuiltinType::U32 { .. } | BuiltinType::U16 => {
35+
RepEquality::Superset
36+
}
3537
_ => RepEquality::NotEq,
3638
},
3739
BuiltinType::U16 => match by {
38-
BuiltinType::U64 | BuiltinType::U32 => RepEquality::Superset,
40+
BuiltinType::U64 | BuiltinType::U32 { .. } => RepEquality::Superset,
3941
_ => RepEquality::NotEq,
4042
},
41-
BuiltinType::U32 => match by {
43+
BuiltinType::U32 { .. } => match by {
4244
BuiltinType::U64 => RepEquality::Superset,
4345
_ => RepEquality::NotEq,
4446
},

tools/witx/src/toplevel.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,12 @@ mod test {
110110
assert_eq!(*b_float.type_(), Type::Builtin(BuiltinType::F64));
111111

112112
let c_int = doc.typename(&Id::new("c_int")).unwrap();
113-
assert_eq!(*c_int.type_(), Type::Builtin(BuiltinType::U32));
113+
assert_eq!(
114+
*c_int.type_(),
115+
Type::Builtin(BuiltinType::U32 {
116+
lang_ptr_size: false
117+
})
118+
);
114119
}
115120

116121
#[test]
@@ -127,7 +132,10 @@ mod test {
127132
.expect("parse");
128133

129134
let d_char = doc.typename(&Id::new("d_char")).unwrap();
130-
assert_eq!(*d_char.type_(), Type::Builtin(BuiltinType::U8));
135+
assert_eq!(
136+
*d_char.type_(),
137+
Type::Builtin(BuiltinType::U8 { lang_c_char: false })
138+
);
131139
}
132140

133141
#[test]

tools/witx/src/validate.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -493,9 +493,9 @@ impl DocValidationScope<'_> {
493493
}
494494
return Ok((e.tag_repr, Some(names)));
495495
}
496-
Type::Builtin(BuiltinType::U8) => return Ok((IntRepr::U8, None)),
496+
Type::Builtin(BuiltinType::U8 { .. }) => return Ok((IntRepr::U8, None)),
497497
Type::Builtin(BuiltinType::U16) => return Ok((IntRepr::U16, None)),
498-
Type::Builtin(BuiltinType::U32) => return Ok((IntRepr::U32, None)),
498+
Type::Builtin(BuiltinType::U32 { .. }) => return Ok((IntRepr::U32, None)),
499499
Type::Builtin(BuiltinType::U64) => return Ok((IntRepr::U64, None)),
500500
_ => {}
501501
}
@@ -522,9 +522,9 @@ impl DocValidationScope<'_> {
522522
span: wast::Span,
523523
) -> Result<IntRepr, ValidationError> {
524524
match type_ {
525-
BuiltinType::U8 => Ok(IntRepr::U8),
525+
BuiltinType::U8 { .. } => Ok(IntRepr::U8),
526526
BuiltinType::U16 => Ok(IntRepr::U16),
527-
BuiltinType::U32 => Ok(IntRepr::U32),
527+
BuiltinType::U32 { .. } => Ok(IntRepr::U32),
528528
BuiltinType::U64 => Ok(IntRepr::U64),
529529
_ => Err(ValidationError::InvalidRepr {
530530
repr: type_.clone(),

tools/witx/tests/multimodule.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,12 @@ fn validate_multimodule() {
1313

1414
// Check that the `a` both modules use is what we expect:
1515
let type_a = doc.typename(&Id::new("a")).expect("type a exists");
16-
assert_eq!(*type_a.type_(), Type::Builtin(BuiltinType::U32));
16+
assert_eq!(
17+
*type_a.type_(),
18+
Type::Builtin(BuiltinType::U32 {
19+
lang_ptr_size: false
20+
})
21+
);
1722

1823
// `b` is a struct with a single member of type `a`
1924
let type_b = doc.typename(&Id::new("b")).expect("type b exists");

0 commit comments

Comments
 (0)