Skip to content

Commit ce93344

Browse files
authored
[cpp] Merge wit-common and wit-guest, install them when generating bindings (#1322)
* Merge wit-common and wit-guest, install them when generating bindings * Switch to C++20 * Fix missing headers, compile in C++20 mode, fix std::span usage * Correct wit.h symlink * Replace old C++ language tests with new one * Fix incorrect header name * Formatting * Fix crate versions
1 parent ee2bb48 commit ce93344

File tree

19 files changed

+235
-164
lines changed

19 files changed

+235
-164
lines changed

crates/cpp/DESIGN.md

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,31 +24,31 @@
2424
| Code | mode | WIT Type | Rust type | C++ Type | Lower | Reason |
2525
| --- | --- | --- | --- | --- | --- | --- |
2626
| GIA | v | string | &str[^1] | string_view (17) | addr, len | |
27-
| | | list | &[T] | wit::span [^5] | addr, len | |
27+
| | | list | &[T] | std::span [^5] | addr, len | |
2828
| | | tuple | (...) | std::tuple | 0, 1, ...| |
2929
| | | tuple<string, list> | (&str, &[T]) | std::tuple<...> | a,l,a,l |
3030
| | | record{string, list} | &T | T const& | a,l,a,l |
3131
| | | large-struct (>16 args) | &T | T const& | &t |
3232
| | | result<string,list> | Result<&str, &[]> | std::expected<string_view, span> | d,a,l |
3333
| | | option\<string> | Option\<&str> | optional<string_view> const& | d,a,l|
3434
| | | list\<resrc> | &[\&Resrc]? | vector<string_view> const& | a,l|
35-
| GIR | t | string | String | wit::string[^2] | &(addr, len) [^8] | |
35+
| GIR | t | string | String | wit::string[^2] | &(addr, len) [^7] | |
3636
| | | list | Vec | wit::vector | &(a,l) |
3737
| | | result<string,list> | Result<String, Vec> | std::expected<wit::string, wit::vector> | &(d,a,l) |
3838
| GEA | t | string | String | 🌓 wit::string | addr, len |
3939
| | | | | ⚖️ string_view | |
4040
| | | result<string,list> | Result<String, Vec> | 🌓 std::expected<wit::string, wit::vector> | d,a,l |
4141
| | | | | ⚖️ std::expected<string_view, wit::span> | |
42-
| GER | p | string | String | wit::string (or std?) | 📘 -> &(a,l) cabi_post_N:P/I#F [^7] |
42+
| GER | p | string | String | wit::string (or std?) | 📘 -> &(a,l) cabi_post_N:P/I#F [^6] |
4343
| | | | | | 🪞 &(a,l) |
4444
| | | result<string,list> | Result<String, Vec> | std::expected<wit::string, wit::vector> | 📘 -> &(d,a,l) cabi_post |
4545
| --S | ? | string | String | wit::string | addr, len |
4646
| HIA | v | string | | string_view | a,l |
4747
| HIR | t | string | | wit::string[^3] | &(a,l) |
4848
| HEA | t | string | | 🌓 wit::string[^4] | a,l |
49-
| | | | | ⚖️ string_view [^6] | |
49+
| | | | | ⚖️ string_view [^5] | |
5050
| HER | p | string | | 🌓 wit::guest_owned<string_view> | 📘 -> &(a,l) |
51-
| | | | | ⚖️ wit::string [^6] | 🪞 &(a,l) |
51+
| | | | | ⚖️ wit::string [^5] | 🪞 &(a,l) |
5252

5353
[^1]: The host never frees memory (is never passed ownership)!
5454

@@ -60,13 +60,11 @@ Complex (non-POD) struct elements on the host will need exec_env to decode or co
6060

6161
[^4]: A host side wit::string doesn't own the data (not free in dtor), thus no move semantics.
6262

63-
[^5]: std::span requires C++-20, this alias should give minimal functionality with older compiler targets.
63+
[^5]: Not implemented, for now symmetric is priority
6464

65-
[^6]: Not implemented, for now symmetric is priority
65+
[^6]: Here the callee (guest) allocates the memory for the set on its side
6666

67-
[^7]: Here the callee (guest) allocates the memory for the set on its side
68-
69-
[^8]: Caller passes address of the return object as argument
67+
[^7]: Caller passes address of the return object as argument
7068

7169
## [Symmetric ABI](https://github.com/WebAssembly/component-model/issues/386)
7270

crates/cpp/helper-types/wit-common.h

Lines changed: 0 additions & 75 deletions
This file was deleted.

crates/cpp/helper-types/wit-guest.h renamed to crates/cpp/helper-types/wit.h

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,50 @@
11
#pragma once
2-
#include "wit-common.h"
3-
#include <malloc.h>
2+
3+
#include <assert.h>
4+
#include <map>
5+
#include <optional>
6+
#include <stddef.h> // size_t
7+
#include <stdint.h>
48
#include <memory> // unique_ptr
59
#include <stdint.h>
610
#include <string>
711
#include <string_view>
812
#include <string.h> // memcpy
913
#include <stdlib.h> // free
1014
#include <new>
15+
#include <span>
1116

1217
namespace wit {
18+
/// @brief Helper class to map between IDs and resources
19+
/// @tparam R Type of the Resource
20+
template <class R> class ResourceTable {
21+
static std::map<int32_t, R> resources;
22+
23+
public:
24+
static R *lookup_resource(int32_t id) {
25+
auto result = resources.find(id);
26+
return result == resources.end() ? nullptr : &result->second;
27+
}
28+
static int32_t store_resource(R &&value) {
29+
auto last = resources.rbegin();
30+
int32_t id = last == resources.rend() ? 0 : last->first + 1;
31+
resources.insert(std::pair<int32_t, R>(id, std::move(value)));
32+
return id;
33+
}
34+
static std::optional<R> remove_resource(int32_t id) {
35+
auto iter = resources.find(id);
36+
std::optional<R> result;
37+
if (iter != resources.end()) {
38+
result = std::move(iter->second);
39+
resources.erase(iter);
40+
}
41+
return std::move(result);
42+
}
43+
};
44+
45+
/// @brief Replaces void in the error position of a result
46+
struct Void {};
47+
1348
/// A string in linear memory, freed unconditionally using free
1449
///
1550
/// A normal C++ string makes no guarantees about where the characters
@@ -112,9 +147,9 @@ template <class T> class vector {
112147
T* leak() { T*result = data_; data_ = nullptr; return result; }
113148
// typically called by post
114149
static void drop_raw(void *ptr) { if (ptr!=empty_ptr()) free(ptr); }
115-
wit::span<T> get_view() const { return wit::span<T>(data_, length); }
116-
wit::span<const T> get_const_view() const { return wit::span<const T>(data_, length); }
117-
template <class U> static vector<T> from_view(wit::span<U> const& a) {
150+
std::span<T> get_view() const { return std::span<T>(data_, length); }
151+
std::span<const T> get_const_view() const { return std::span<const T>(data_, length); }
152+
template <class U> static vector<T> from_view(std::span<U> const& a) {
118153
auto result = vector<T>::allocate(a.size());
119154
for (uint32_t i=0;i<a.size();++i) {
120155
new ((void*)(result.data_+i)) T(a[i]);

crates/cpp/src/lib.rs

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ struct Includes {
8080
needs_variant: bool,
8181
needs_tuple: bool,
8282
needs_assert: bool,
83+
needs_bit: bool,
84+
needs_span: bool,
8385
// needs wit types
8486
needs_wit: bool,
8587
needs_memory: bool,
@@ -339,20 +341,20 @@ impl Cpp {
339341
fn perform_cast(&mut self, op: &str, cast: &Bitcast) -> String {
340342
match cast {
341343
Bitcast::I32ToF32 | Bitcast::I64ToF32 => {
342-
self.dependencies.needs_wit = true;
343-
format!("wit::bit_cast<float, int32_t>({})", op)
344+
self.dependencies.needs_bit = true;
345+
format!("std::bit_cast<float, int32_t>({})", op)
344346
}
345347
Bitcast::F32ToI32 | Bitcast::F32ToI64 => {
346-
self.dependencies.needs_wit = true;
347-
format!("wit::bit_cast<int32_t, float>({})", op)
348+
self.dependencies.needs_bit = true;
349+
format!("std::bit_cast<int32_t, float>({})", op)
348350
}
349351
Bitcast::I64ToF64 => {
350-
self.dependencies.needs_wit = true;
351-
format!("wit::bit_cast<double, int64_t>({})", op)
352+
self.dependencies.needs_bit = true;
353+
format!("std::bit_cast<double, int64_t>({})", op)
352354
}
353355
Bitcast::F64ToI64 => {
354-
self.dependencies.needs_wit = true;
355-
format!("wit::bit_cast<int64_t, double>({})", op)
356+
self.dependencies.needs_bit = true;
357+
format!("std::bit_cast<int64_t, double>({})", op)
356358
}
357359
Bitcast::I32ToI64 | Bitcast::LToI64 | Bitcast::PToP64 => {
358360
format!("(int64_t) {}", op)
@@ -409,11 +411,14 @@ impl Cpp {
409411
self.include("<tuple>");
410412
}
411413
if self.dependencies.needs_wit {
412-
self.include("<wit-guest.h>");
414+
self.include("\"wit.h\"");
413415
}
414416
if self.dependencies.needs_memory {
415417
self.include("<memory>");
416418
}
419+
if self.dependencies.needs_bit {
420+
self.include("<bit>");
421+
}
417422
}
418423

419424
fn start_new_file(&mut self, condition: Option<bool>) -> FileContext {
@@ -715,6 +720,10 @@ impl WorldGenerator for Cpp {
715720
.as_slice(),
716721
);
717722

723+
if self.dependencies.needs_wit {
724+
files.push(&format!("wit.h"), include_bytes!("../helper-types/wit.h"));
725+
}
726+
718727
Ok(())
719728
}
720729
}
@@ -1520,15 +1529,15 @@ impl CppInterfaceGenerator<'_> {
15201529
let inner = self.type_name(ty, from_namespace, flavor);
15211530
match flavor {
15221531
Flavor::BorrowedArgument => {
1523-
self.gen.dependencies.needs_wit = true;
1524-
format!("wit::span<{inner} const>")
1532+
self.gen.dependencies.needs_span = true;
1533+
format!("std::span<{inner} const>")
15251534
}
15261535
Flavor::Argument(var)
15271536
if matches!(var, AbiVariant::GuestImport)
15281537
|| self.gen.opts.api_style == APIStyle::Symmetric =>
15291538
{
1530-
self.gen.dependencies.needs_wit = true;
1531-
format!("wit::span<{inner} const>")
1539+
self.gen.dependencies.needs_span = true;
1540+
format!("std::span<{inner} const>")
15321541
}
15331542
Flavor::Argument(AbiVariant::GuestExport) => {
15341543
self.gen.dependencies.needs_wit = true;

crates/cpp/test_headers/wit-common.h

Lines changed: 0 additions & 1 deletion
This file was deleted.

crates/cpp/test_headers/wit-guest.h

Lines changed: 0 additions & 1 deletion
This file was deleted.

crates/cpp/test_headers/wit.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../helper-types/wit.h

crates/test/src/cpp.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use std::process::Command;
88

99
// option wasi_sdk_path is inherited from C
1010

11-
pub struct Cpp17;
11+
pub struct Cpp;
1212

1313
/// C/C++-specific configuration of component files
1414
#[derive(Default, Deserialize)]
@@ -26,9 +26,9 @@ fn clangpp(runner: &Runner<'_>) -> PathBuf {
2626
}
2727
}
2828

29-
impl LanguageMethods for Cpp17 {
29+
impl LanguageMethods for Cpp {
3030
fn display(&self) -> &str {
31-
"cpp17"
31+
"cpp"
3232
}
3333

3434
fn comment_prefix_for_test_config(&self) -> Option<&str> {
@@ -76,7 +76,7 @@ impl LanguageMethods for Cpp17 {
7676
) -> anyhow::Result<()> {
7777
let mut export_header_dir = bindgen.wit_path.clone();
7878
export_header_dir.pop();
79-
export_header_dir.push("cpp17");
79+
export_header_dir.push("cpp");
8080

8181
// copy resource implementation in header files to target dir
8282
if export_header_dir.is_dir() {
@@ -131,7 +131,7 @@ impl LanguageMethods for Cpp17 {
131131
.arg("-Wextra")
132132
.arg("-Werror")
133133
.arg("-Wno-unused-parameter")
134-
.arg("-std=c++17")
134+
.arg("-std=c++20")
135135
.arg("-c")
136136
.arg("-g")
137137
.arg("-o")
@@ -159,7 +159,7 @@ impl LanguageMethods for Cpp17 {
159159
.arg("-Werror")
160160
.arg("-Wc++-compat")
161161
.arg("-Wno-unused-parameter")
162-
.arg("-std=c++17")
162+
.arg("-std=c++20")
163163
.arg("-g")
164164
.arg("-o")
165165
.arg(&compile.output);

0 commit comments

Comments
 (0)