Skip to content

Commit

Permalink
initial version of meshless strings, still wrong handling of malloc/free
Browse files Browse the repository at this point in the history
  • Loading branch information
cpetig committed Jun 23, 2024
1 parent d0ede2b commit be3ac11
Show file tree
Hide file tree
Showing 10 changed files with 340 additions and 0 deletions.
4 changes: 4 additions & 0 deletions crates/cpp/helper-types/wit-guest.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ class string {
std::string to_string() const {
return std::string((const char *)data_, length);
}
static string from_view(std::string_view v) {
char* addr = (char*)malloc(v.size());
return string(addr, v.size());
}
};

/// A vector in linear memory, freed unconditionally using free
Expand Down
1 change: 1 addition & 0 deletions crates/cpp/tests/meshless_strings/Makefile
12 changes: 12 additions & 0 deletions crates/cpp/tests/meshless_strings/component_a/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
CXXFLAGS=-g -O0 -I../../../helper-types

all: component_a

component_a: the_world.cpp main.cpp
$(CXX) $(CXXFLAGS) -o $@ $^ -L../component_b -lcomponent_b

bindgen:
../../../../../target/debug/wit-bindgen cpp ../wit -w a --wasm64 --format

clean:
-rm *~ component_a *.o
30 changes: 30 additions & 0 deletions crates/cpp/tests/meshless_strings/component_a/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@

#include "the_world_cpp.h"
#include <iostream>

void comp_a::exports::foo::foo::strings::A(wit::string &&x) {
std::cout << x.get_view() << std::endl;
}
wit::string comp_a::exports::foo::foo::strings::B() {
wit::string b = wit::string::from_view(std::string_view("hello B"));
return b;
}
wit::string comp_a::exports::foo::foo::strings::C(wit::string &&a, wit::string &&b) {
std::cout << a.get_view() << '|' << b.get_view() << std::endl;
wit::string c = wit::string::from_view(std::string_view("hello C"));
return c;
}

int main() {
comp_a::foo::foo::strings::A(std::string_view("hello A"));

{
auto b = comp_a::foo::foo::strings::B();
std::cout << b.get_view() << std::endl;
// make sure that b's result is destructed before calling C
}

auto c = comp_a::foo::foo::strings::C(std::string_view("hello C1"), std::string_view("hello C2"));
std::cout << c.get_view() << std::endl;
return 0;
}
123 changes: 123 additions & 0 deletions crates/cpp/tests/meshless_strings/component_a/the_world.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
// Generated by `wit-bindgen` 0.3.0. DO NOT EDIT!

// Ensure that the *_component_type.o object is linked in
#ifdef __wasm32__
extern void __component_type_object_force_link_the_world(void);
void __component_type_object_force_link_the_world_public_use_in_this_compilation_unit(
void) {
__component_type_object_force_link_the_world();
}
#endif
#include "the_world_cpp.h"
#include <cstdlib> // realloc

extern "C" void *cabi_realloc(void *ptr, size_t old_size, size_t align,
size_t new_size);

__attribute__((__weak__, __export_name__("cabi_realloc"))) void *
cabi_realloc(void *ptr, size_t old_size, size_t align, size_t new_size) {
(void)old_size;
if (new_size == 0)
return (void *)align;
void *ret = realloc(ptr, new_size);
if (!ret)
abort();
return ret;
}

extern "C" __attribute__((import_module("foo:foo/strings")))
__attribute__((import_name("a"))) void
fooX3AfooX2FstringsX00a(uint8_t *, size_t);
extern "C" __attribute__((import_module("foo:foo/strings")))
__attribute__((import_name("b"))) void
fooX3AfooX2FstringsX00b(uint8_t *);
extern "C" __attribute__((import_module("foo:foo/strings")))
__attribute__((import_name("c"))) void
fooX3AfooX2FstringsX00c(uint8_t *, size_t, uint8_t *, size_t, uint8_t *);
void comp_a::foo::foo::strings::A(std::string_view x) {
auto const &vec0 = x;
auto ptr0 = (uint8_t *)(vec0.data());
auto len0 = (size_t)(vec0.size());
fooX3AfooX2FstringsX00a(ptr0, len0);
}
wit::string comp_a::foo::foo::strings::B() {
size_t ret_area[2];
uint8_t *ptr0 = (uint8_t *)(&ret_area);
fooX3AfooX2FstringsX00b(ptr0);
auto len1 = *((size_t *)(ptr0 + sizeof(size_t)));

return wit::string((char const *)(*((uint8_t **)(ptr0 + 0))), len1);
}
wit::string comp_a::foo::foo::strings::C(std::string_view a, std::string_view b) {
auto const &vec0 = a;
auto ptr0 = (uint8_t *)(vec0.data());
auto len0 = (size_t)(vec0.size());
auto const &vec1 = b;
auto ptr1 = (uint8_t *)(vec1.data());
auto len1 = (size_t)(vec1.size());
size_t ret_area[2];
uint8_t *ptr2 = (uint8_t *)(&ret_area);
fooX3AfooX2FstringsX00c(ptr0, len0, ptr1, len1, ptr2);
auto len3 = *((size_t *)(ptr2 + sizeof(size_t)));

return wit::string((char const *)(*((uint8_t **)(ptr2 + 0))), len3);
}
extern "C" __attribute__((__export_name__("foo:foo/strings#a"))) void
a_fooX3AfooX2FstringsX00a(uint8_t *arg0, size_t arg1) {
auto len0 = arg1;

exports::foo::foo::strings::A(wit::string((char const *)(arg0), len0));
}
extern "C" __attribute__((__export_name__("foo:foo/strings#b"))) uint8_t *
a_fooX3AfooX2FstringsX00b() {
auto result0 = exports::foo::foo::strings::B();
static size_t ret_area[2];
uint8_t *ptr1 = (uint8_t *)(&ret_area);
auto const &vec2 = result0;
auto ptr2 = (uint8_t *)(vec2.data());
auto len2 = (size_t)(vec2.size());
result0.leak();

*((size_t *)(ptr1 + sizeof(size_t))) = len2;
*((uint8_t **)(ptr1 + 0)) = ptr2;
return ptr1;
}
extern "C"
__attribute__((__weak__,
__export_name__("cabi_post_fooX3AfooX2FstringsX23b"))) void
a_cabi_post_fooX3AfooX2FstringsX00b(uint8_t *arg0) {
if ((*((size_t *)(arg0 + sizeof(size_t)))) > 0) {
wit::string::drop_raw((void *)(*((uint8_t **)(arg0 + 0))));
}
}
extern "C" __attribute__((__export_name__("foo:foo/strings#c"))) uint8_t *
a_fooX3AfooX2FstringsX00c(uint8_t *arg0, size_t arg1, uint8_t *arg2,
size_t arg3) {
auto len0 = arg1;

auto len1 = arg3;

auto result2 =
exports::foo::foo::strings::C(wit::string((char const *)(arg0), len0),
wit::string((char const *)(arg2), len1));
static size_t ret_area[2];
uint8_t *ptr3 = (uint8_t *)(&ret_area);
auto const &vec4 = result2;
auto ptr4 = (uint8_t *)(vec4.data());
auto len4 = (size_t)(vec4.size());
result2.leak();

*((size_t *)(ptr3 + sizeof(size_t))) = len4;
*((uint8_t **)(ptr3 + 0)) = ptr4;
return ptr3;
}
extern "C"
__attribute__((__weak__,
__export_name__("cabi_post_fooX3AfooX2FstringsX23c"))) void
a_cabi_post_fooX3AfooX2FstringsX00c(uint8_t *arg0) {
if ((*((size_t *)(arg0 + sizeof(size_t)))) > 0) {
wit::string::drop_raw((void *)(*((uint8_t **)(arg0 + 0))));
}
}

// Component Adapters
33 changes: 33 additions & 0 deletions crates/cpp/tests/meshless_strings/component_a/the_world_cpp.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Generated by `wit-bindgen` 0.3.0. DO NOT EDIT!
#ifndef __CPP_GUEST_BINDINGS_THE_WORLD_H
#define __CPP_GUEST_BINDINGS_THE_WORLD_H
#include <cstdint>
#include <string_view>
#include <utility>
#include <wit-guest.h>
namespace comp_a {
namespace foo {
namespace foo {
namespace strings {
void A(std::string_view x);
wit::string B();
wit::string C(std::string_view a, std::string_view b);
// export_interface Interface(Id { idx: 0 })
} // namespace strings
} // namespace foo
} // namespace foo
namespace exports {
namespace foo {
namespace foo {
namespace strings {
void A(wit::string &&x);
wit::string B();
wit::string C(wit::string &&a, wit::string &&b);
} // namespace strings
} // namespace foo
} // namespace foo
} // namespace exports
}
using namespace comp_a;
//using namespace A::foo;
#endif
12 changes: 12 additions & 0 deletions crates/cpp/tests/meshless_strings/component_b/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
CXXFLAGS=-g -O0 -I../../../helper-types

all: libcomponent_b.a

libcomponent_b.a: the_world.o guest.o
ar rcvs $@ $^

bindgen:
../../../../../target/debug/wit-bindgen cpp ../wit -w b --wasm64 --format

clean:
-rm *~ *.a *.o
1 change: 1 addition & 0 deletions crates/cpp/tests/meshless_strings/component_b/guest.cpp
123 changes: 123 additions & 0 deletions crates/cpp/tests/meshless_strings/component_b/the_world.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
// Generated by `wit-bindgen` 0.3.0. DO NOT EDIT!

// Ensure that the *_component_type.o object is linked in
#ifdef __wasm32__
extern void __component_type_object_force_link_the_world(void);
void __component_type_object_force_link_the_world_public_use_in_this_compilation_unit(
void) {
__component_type_object_force_link_the_world();
}
#endif
#include "the_world_cpp.h"
#include <cstdlib> // realloc

extern "C" void *cabi_realloc(void *ptr, size_t old_size, size_t align,
size_t new_size);

__attribute__((__weak__, __export_name__("cabi_realloc"))) void *
cabi_realloc(void *ptr, size_t old_size, size_t align, size_t new_size) {
(void)old_size;
if (new_size == 0)
return (void *)align;
void *ret = realloc(ptr, new_size);
if (!ret)
abort();
return ret;
}

extern "C" __attribute__((import_module("foo:foo/strings")))
__attribute__((import_name("a"))) void
a_fooX3AfooX2FstringsX00a(uint8_t *, size_t);
extern "C" __attribute__((import_module("foo:foo/strings")))
__attribute__((import_name("b"))) void
a_fooX3AfooX2FstringsX00b(uint8_t *);
extern "C" __attribute__((import_module("foo:foo/strings")))
__attribute__((import_name("c"))) void
a_fooX3AfooX2FstringsX00c(uint8_t *, size_t, uint8_t *, size_t, uint8_t *);
void foo::foo::strings::A(std::string_view x) {
auto const &vec0 = x;
auto ptr0 = (uint8_t *)(vec0.data());
auto len0 = (size_t)(vec0.size());
a_fooX3AfooX2FstringsX00a(ptr0, len0);
}
wit::string foo::foo::strings::B() {
size_t ret_area[2];
uint8_t *ptr0 = (uint8_t *)(&ret_area);
a_fooX3AfooX2FstringsX00b(ptr0);
auto len1 = *((size_t *)(ptr0 + sizeof(size_t)));

return wit::string((char const *)(*((uint8_t **)(ptr0 + 0))), len1);
}
wit::string foo::foo::strings::C(std::string_view a, std::string_view b) {
auto const &vec0 = a;
auto ptr0 = (uint8_t *)(vec0.data());
auto len0 = (size_t)(vec0.size());
auto const &vec1 = b;
auto ptr1 = (uint8_t *)(vec1.data());
auto len1 = (size_t)(vec1.size());
size_t ret_area[2];
uint8_t *ptr2 = (uint8_t *)(&ret_area);
a_fooX3AfooX2FstringsX00c(ptr0, len0, ptr1, len1, ptr2);
auto len3 = *((size_t *)(ptr2 + sizeof(size_t)));

return wit::string((char const *)(*((uint8_t **)(ptr2 + 0))), len3);
}
extern "C" __attribute__((__export_name__("foo:foo/strings#a"))) void
fooX3AfooX2FstringsX00a(uint8_t *arg0, size_t arg1) {
auto len0 = arg1;

exports::foo::foo::strings::A(wit::string((char const *)(arg0), len0));
}
extern "C" __attribute__((__export_name__("foo:foo/strings#b"))) uint8_t *
fooX3AfooX2FstringsX00b() {
auto result0 = exports::foo::foo::strings::B();
static size_t ret_area[2];
uint8_t *ptr1 = (uint8_t *)(&ret_area);
auto const &vec2 = result0;
auto ptr2 = (uint8_t *)(vec2.data());
auto len2 = (size_t)(vec2.size());
result0.leak();

*((size_t *)(ptr1 + sizeof(size_t))) = len2;
*((uint8_t **)(ptr1 + 0)) = ptr2;
return ptr1;
}
extern "C"
__attribute__((__weak__,
__export_name__("cabi_post_fooX3AfooX2FstringsX23b"))) void
cabi_post_fooX3AfooX2FstringsX00b(uint8_t *arg0) {
if ((*((size_t *)(arg0 + sizeof(size_t)))) > 0) {
wit::string::drop_raw((void *)(*((uint8_t **)(arg0 + 0))));
}
}
extern "C" __attribute__((__export_name__("foo:foo/strings#c"))) uint8_t *
fooX3AfooX2FstringsX00c(uint8_t *arg0, size_t arg1, uint8_t *arg2,
size_t arg3) {
auto len0 = arg1;

auto len1 = arg3;

auto result2 =
exports::foo::foo::strings::C(wit::string((char const *)(arg0), len0),
wit::string((char const *)(arg2), len1));
static size_t ret_area[2];
uint8_t *ptr3 = (uint8_t *)(&ret_area);
auto const &vec4 = result2;
auto ptr4 = (uint8_t *)(vec4.data());
auto len4 = (size_t)(vec4.size());
result2.leak();

*((size_t *)(ptr3 + sizeof(size_t))) = len4;
*((uint8_t **)(ptr3 + 0)) = ptr4;
return ptr3;
}
extern "C"
__attribute__((__weak__,
__export_name__("cabi_post_fooX3AfooX2FstringsX23c"))) void
cabi_post_fooX3AfooX2FstringsX00c(uint8_t *arg0) {
if ((*((size_t *)(arg0 + sizeof(size_t)))) > 0) {
wit::string::drop_raw((void *)(*((uint8_t **)(arg0 + 0))));
}
}

// Component Adapters

0 comments on commit be3ac11

Please sign in to comment.