Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/ci-all-samples.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,4 @@ jobs:
uses: actions/checkout@v2
- run: make -C ${{ github.workspace }} -j$(sysctl -n hw.physicalcpu) run
- run: echo "Tests completed"

15 changes: 8 additions & 7 deletions include/blocks/c_code_generator.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@

#include "blocks/block_visitor.h"
#include "blocks/stmt.h"
#include "builder/dyn_var.h"
#include "util/printer.h"
#include <unordered_map>
#include <unordered_set>
#include "builder/forward_declarations.h"
#include "builder/providers_dyn_var.h"

namespace block {
class c_code_generator : public block_visitor {
Expand Down Expand Up @@ -116,11 +117,11 @@ class c_code_generator : public block_visitor {
}
template <typename T>
static void generate_struct_decl(std::ostream &oss, int indent = 0) {
static_assert(std::is_base_of<builder::var, T>::value, "Template argument should be a dyn_var");
auto save = builder::options::track_members;
builder::options::track_members = true;
static_assert(builder::is_dyn_var_type<T>::value, "Template argument should be a dyn_var");
auto save = builder::user_defined_provider_track_members;
builder::user_defined_provider_track_members = true;
T v = builder::with_name("_");
builder::options::track_members = save;
builder::user_defined_provider_track_members = save;

// Construct a struct decl
auto sd = std::make_shared<struct_decl>();
Expand All @@ -130,9 +131,9 @@ class c_code_generator : public block_visitor {
"Cannot yet, generate decls for types with template args");

sd->struct_name = to<named_type>(var_type)->type_name;
for (auto member: v.members) {
for (auto member: v.user_defined_members) {
auto decl = std::make_shared<decl_stmt>();
decl->decl_var = member->block_var;
decl->decl_var = member;
decl->init_expr = nullptr;
sd->members.push_back(decl);
}
Expand Down
129 changes: 129 additions & 0 deletions include/builder/arena_dyn_var.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
#ifndef ARENA_DYN_VAR_H
#define ARENA_DYN_VAR_H
#include <cstddef>

namespace builder {

using byte_t = unsigned char;
struct arena_list {
std::vector<byte_t*> chunks;
size_t used_objects = 0;
};

constexpr const int arena_objects_per_chunk = 64;

// Registry type for types that are allocatable
// Each global construct call assigns a unique id to each type
struct allocatable_type_registry {
// Declaration for unique counter, definition is in cpp
static int type_counter;

// A function that can destroy a list of objects of a type
using deleter_t = void(*)(arena_list*);

// This has to be a pointer because we cannot guarantee order of invocation of constructors
static std::vector<deleter_t> *type_deleters;

int type_id;

// Grab an ID and increment
allocatable_type_registry(deleter_t deleter) {
if (type_deleters == nullptr) {
type_deleters = new std::vector<deleter_t>();
}
type_deleters->push_back(deleter);
type_id = type_counter;
type_counter++;
}

// Post global constructor, this returns the maximum
// type id. Make sure this is ONLY called from main
static int get_max_type_id(void) {
return type_counter;
}
};

// This type is instantiated for each
// type that is allocated in the whole binary
template <typename T>
struct allocatable_type_manager {
static allocatable_type_registry register_type;
static void delete_objects(arena_list *list) {
for (size_t i = 0; i < list->used_objects; i++) {
int chunk_id = i / arena_objects_per_chunk;
int chunk_offset = i % arena_objects_per_chunk;

auto ptr_b = list->chunks[chunk_id] + sizeof(T) * chunk_offset;
auto ptr = (T*)ptr_b;
ptr->~T();
}
list->used_objects = 0;
}
};

template <typename T>
allocatable_type_registry allocatable_type_manager<T>::register_type(allocatable_type_manager<T>::delete_objects);

class dyn_var_arena {
// Arena contains a separate list for each type
// indexed by a generated type id
std::vector<arena_list> arena_lists;

template <typename T>
byte_t* grab_buffer() {
// Get arena list index for this type
int index = allocatable_type_manager<T>::register_type.type_id;
arena_list& list = arena_lists[index];
// If list is full add another chunk
if (list.used_objects == list.chunks.size() * arena_objects_per_chunk) {
// Alignment and pointer and the end
static_assert(alignof(T) <= alignof(std::max_align_t),
"Allocated type has higher alignment requirement that std::max_align_t"
"needs manual alignment");
byte_t* new_chunk = new byte_t[sizeof(T) * arena_objects_per_chunk];
list.chunks.push_back(new_chunk);
}
int chunk_id = list.used_objects / arena_objects_per_chunk;
int chunk_offset = list.used_objects % arena_objects_per_chunk;

auto ptr = list.chunks[chunk_id] + sizeof(T) * chunk_offset;
list.used_objects++;
return ptr;
}

public:

dyn_var_arena() {
arena_lists.resize(allocatable_type_registry::get_max_type_id());
}

template <typename T, typename...Args>
T* allocate(Args&&...args) {
auto ptr_b = grab_buffer<T>();
auto ptr = new (ptr_b) T(std::forward<Args>(args)...);
return ptr;
}


void reset_arena(void) {
// For each type call the respective deleters on the type
for (unsigned int i = 0; i < arena_lists.size(); i++) {
if (arena_lists[i].used_objects > 0) {
(*allocatable_type_registry::type_deleters)[i](&(arena_lists[i]));
}
}
}

~dyn_var_arena() {
reset_arena();
for (auto& a: arena_lists) {
for (auto c: a.chunks) {
delete[] c;
}
}
}
};

}

#endif
10 changes: 3 additions & 7 deletions include/builder/array.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,18 @@

namespace builder {


// If the array is of dyn_vars, we initialize with a
// builder, anything else and we directly initialize with T
// This avoids unnecessary copies unless entirely necessary
// This helper avoids unnecessary copies for
// dyn_var objects
template <typename T>
struct initializer_selector {
typedef const T type;
};

template <typename T>
struct initializer_selector<dyn_var<T>> {
typedef builder type;
typedef expr_wrapper type;
};



template <typename T, size_t size = 0>
class array {
private:
Expand Down
51 changes: 3 additions & 48 deletions include/builder/block_type_extractor.h
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
#ifndef TYPE_EXTRACTOR_H
#define TYPE_EXTRACTOR_H


#include "builder/forward_declarations.h"
#include "util/mtp_utils.h"
#include "builder/generics.h"
#include <algorithm>

namespace builder {

struct custom_type_base;

template <typename T>
struct external_type_namer;
Expand Down Expand Up @@ -83,10 +80,8 @@ template <typename T>
class type_extractor {
public:
// This implementation is currenty only used
// by custom types which are derived from custom_type_base
// by custom types which are derived from custom_type
static block::type::Ptr extract_type(void) {
//static_assert(std::is_base_of<custom_type_base, T>::value,
//"Custom types should inherit from builder::custom_type_base");
block::named_type::Ptr type = std::make_shared<block::named_type>();
type->type_name = type_namer<T>::get_type_name();
type->template_args = type_template<T>::get_templates();
Expand Down Expand Up @@ -345,67 +340,27 @@ class type_extractor<generic> {
};



// Extracting function types
template <typename... args>
std::vector<block::type::Ptr> extract_type_vector_dyn(void);

template <typename T, typename... args>
std::vector<block::type::Ptr> extract_type_vector_helper_dyn(void) {
std::vector<block::type::Ptr> rest = extract_type_vector_dyn<args...>();
rest.push_back(type_extractor<T>::extract_type());
return rest;
}

template <typename... args>
std::vector<block::type::Ptr> extract_type_vector_dyn(void) {
return extract_type_vector_helper_dyn<args...>();
}

template <>
std::vector<block::type::Ptr> extract_type_vector_dyn<>(void);

template <typename r_type, typename... a_types>
class type_extractor<r_type(a_types...)> {
public:
static block::type::Ptr extract_type(void) {
block::function_type::Ptr type = std::make_shared<block::function_type>();
type->return_type = type_extractor<r_type>::extract_type();
type->arg_types = extract_type_vector_dyn<a_types...>();
std::reverse(type->arg_types.begin(), type->arg_types.end());
type->arg_types = std::vector<block::type::Ptr>({type_extractor<a_types>::extract_type()...});
return type;
}
};

template <const char *N, typename... Args>
struct name {};

template <typename... Args>
struct extract_type_from_args;

template <typename T1, typename... Args>
struct extract_type_from_args<T1, Args...> {
static std::vector<block::type::Ptr> get_types() {
auto a = extract_type_from_args<Args...>::get_types();
a.insert(a.begin(), type_extractor<T1>::extract_type());
return a;
}
};

template <>
struct extract_type_from_args<> {
static std::vector<block::type::Ptr> get_types() {
return std::vector<block::type::Ptr>();
}
};

template <const char *N, typename... Args>
class type_extractor<name<N, Args...>> {
public:
static block::type::Ptr extract_type(void) {
block::named_type::Ptr type = std::make_shared<block::named_type>();
type->type_name = N;
type->template_args = extract_type_from_args<Args...>::get_types();
type->template_args = {type_extractor<Args>::extract_type()...};
return type;
}
};
Expand Down
11 changes: 0 additions & 11 deletions include/builder/builder.h

This file was deleted.

Loading