Skip to content

Commit

Permalink
step1, sized enums: output definitions + static_assert for sizes and …
Browse files Browse the repository at this point in the history
…alingment
  • Loading branch information
wc-duck committed May 23, 2018
1 parent d71afa3 commit c0c32c5
Show file tree
Hide file tree
Showing 9 changed files with 132 additions and 15 deletions.
3 changes: 2 additions & 1 deletion bam.lua
Original file line number Diff line number Diff line change
Expand Up @@ -200,9 +200,10 @@ end

function make_test_settings( base_settings )
local settings = TableDeepCopy( base_settings )

if settings.platform == 'linux_x86' or settings.platform == 'linux_x86_64' then
settings.cc.flags:Add("-Wall","-Werror", "-Wextra", "-Wconversion", "-Wstrict-aliasing=2")
settings.cc.flags_cxx:Add("-std=c++11") -- enabled to test out sized enums.
else
--[[
/EHsc only on unittest
Expand Down
7 changes: 4 additions & 3 deletions include/dl/dl_reflect.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,10 @@ typedef struct dl_member_info
*/
typedef struct dl_enum_info
{
dl_typeid_t tid;
const char* name;
unsigned int value_count;
dl_typeid_t tid;
const char* name;
dl_type_storage_t storage;
unsigned int value_count;
} dl_enum_info_t;

/*
Expand Down
1 change: 1 addition & 0 deletions src/dl_reflect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ static void dl_reflect_copy_enum_info( dl_ctx_t ctx, dl_enum_info_t* enuminfo, c
{
enuminfo->tid = ctx->enum_ids[ enum_ - ctx->enum_descs ];
enuminfo->name = dl_internal_enum_name( ctx, enum_ );
enuminfo->storage = enum_->storage;
enuminfo->value_count = enum_->value_count;
}

Expand Down
52 changes: 48 additions & 4 deletions src/dl_typelib_read_txt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -307,8 +307,8 @@ static void dl_load_txt_calc_type_size_and_align( dl_ctx_t ctx, dl_txt_read_ctx*
// If a member is marked as a struct it could also have been an enum that we didn't know about parse-time, patch it in that case.
if( member->StorageType() == DL_TYPE_STORAGE_STRUCT )
{
if( dl_internal_find_enum( ctx, member->type_id ) )
member->set_storage( DL_TYPE_STORAGE_ENUM_UINT32 );
if( const dl_enum_desc* edesc = dl_internal_find_enum( ctx, member->type_id ) )
member->set_storage( edesc->storage );
}

dl_type_atom_t atom = member->AtomType();
Expand Down Expand Up @@ -550,6 +550,7 @@ static void dl_context_load_txt_type_library_read_enum( dl_ctx_t ctx, dl_txt_rea
{
uint32_t value_start = ctx->enum_value_count;
uint32_t alias_start = ctx->enum_alias_count;
dl_type_storage_t storage = DL_TYPE_STORAGE_CNT;

dl_txt_eat_char( ctx, read_state, '{' );
do
Expand All @@ -572,15 +573,58 @@ static void dl_context_load_txt_type_library_read_enum( dl_ctx_t ctx, dl_txt_rea
} while( dl_txt_try_eat_char( read_state, ',') );
dl_txt_eat_char( ctx, read_state, '}' );
}
else if( strncmp( "type", key.str, 4 ) == 0 )
{
if(storage != DL_TYPE_STORAGE_CNT)
dl_txt_read_failed( ctx, read_state, DL_ERROR_MALFORMED_DATA, "'type' set twice on enum '%.*s'", name->len, name->str );

dl_txt_read_substr type_str = dl_txt_eat_and_expect_string( ctx, read_state );
switch(type_str.len)
{
case 4:
{
if( strncmp("int8", type_str.str, 4) == 0 )
storage = DL_TYPE_STORAGE_ENUM_INT8;
}
break;
case 5:
{
if( strncmp("int16", type_str.str, 5) == 0 ) storage = DL_TYPE_STORAGE_ENUM_INT16;
else if( strncmp("int32", type_str.str, 5) == 0 ) storage = DL_TYPE_STORAGE_ENUM_INT32;
else if( strncmp("int64", type_str.str, 5) == 0 ) storage = DL_TYPE_STORAGE_ENUM_INT64;
else if( strncmp("uint8", type_str.str, 5) == 0 ) storage = DL_TYPE_STORAGE_ENUM_UINT8;
}
break;
case 6:
{
if( strncmp("uint16", type_str.str, 6) == 0 ) storage = DL_TYPE_STORAGE_ENUM_UINT16;
else if( strncmp("uint32", type_str.str, 6) == 0 ) storage = DL_TYPE_STORAGE_ENUM_UINT32;
else if( strncmp("uint64", type_str.str, 6) == 0 ) storage = DL_TYPE_STORAGE_ENUM_UINT64;
}
break;
default:
break;
}

if(storage == DL_TYPE_STORAGE_CNT)
dl_txt_read_failed( ctx, read_state, DL_ERROR_MALFORMED_DATA,
"'type' on enum '%.*s' set to '%.*s', valid types are 'int8', 'int16', 'int32', 'int64', 'uint8', 'uint16', 'uint32' and 'uint64'",
name->len, name->str,
type_str.len, type_str.str );
}
else
dl_txt_read_failed( ctx, read_state, DL_ERROR_MALFORMED_DATA, "unexpected key '%.*s' in type, valid keys are 'values'", key.len, key.str );
dl_txt_read_failed( ctx, read_state, DL_ERROR_MALFORMED_DATA, "unexpected key '%.*s' in type, valid keys are 'values' and 'type'", key.len, key.str );

} while( dl_txt_try_eat_char( read_state, ',') );
dl_txt_eat_char( ctx, read_state, '}' );

// TODO: add test for missing enum value ...

if(storage == DL_TYPE_STORAGE_CNT )
storage = DL_TYPE_STORAGE_ENUM_UINT32; // default to uint32

dl_enum_desc* edesc = dl_alloc_enum(ctx, name);
edesc->storage = storage;
edesc->value_count = ctx->enum_value_count - value_start;
edesc->value_start = value_start;
edesc->alias_count = ctx->enum_alias_count - alias_start; /// number of aliases for this enum, always at least 1. Alias 0 is consider the "main name" of the value and need to be a valid c enum name.
Expand Down Expand Up @@ -1000,7 +1044,7 @@ static void dl_context_load_txt_type_library_inner( dl_ctx_t ctx, dl_txt_read_ct
if( enum_sub_type )
{
// ... type was really an enum ...
member->set_storage( DL_TYPE_STORAGE_ENUM_UINT32 );
member->set_storage( enum_sub_type->storage );
}
else
{
Expand Down
33 changes: 32 additions & 1 deletion src/dl_typelib_write_c_header.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ static void dl_context_write_c_header_begin( dl_binary_writer* writer, const cha
"\n"
"# ifndef DL_ALIGNOF\n"
"# define DL_ALIGNOF(type) ((sizeof(type) > 1)? offsetof(struct { char c; type x; }, x) : 1)\n"
//"# define DL_ALIGNOF(type) alignof(type)\n"
"# endif\n"
"\n"
" // ... DL_STATIC_ASSERT() ...\n"
Expand Down Expand Up @@ -107,7 +108,27 @@ static void dl_context_write_c_header_enums( dl_binary_writer* writer, dl_ctx_t
dl_enum_info_t enum_info;
dl_reflect_get_enum_info( ctx, tids[enum_index], &enum_info );

dl_binary_writer_write_string_fmt( writer, "enum %s\n{\n", enum_info.name );
const char* storage_decl = "";
switch(enum_info.storage)
{
case DL_TYPE_STORAGE_ENUM_INT8: storage_decl = " : int8_t"; break;
case DL_TYPE_STORAGE_ENUM_INT16: storage_decl = " : int16_t"; break;
case DL_TYPE_STORAGE_ENUM_INT32: storage_decl = " : int32_t"; break;
case DL_TYPE_STORAGE_ENUM_INT64: storage_decl = " : int64_t"; break;
case DL_TYPE_STORAGE_ENUM_UINT8: storage_decl = " : uint8_t"; break;
case DL_TYPE_STORAGE_ENUM_UINT16: storage_decl = " : uint16_t"; break;
case DL_TYPE_STORAGE_ENUM_UINT32: break; // no decl on 32-bit enums as that is default-size.
case DL_TYPE_STORAGE_ENUM_UINT64: storage_decl = " : uint64_t"; break;
default:
break;
}

if(enum_info.storage != DL_TYPE_STORAGE_ENUM_UINT32)
dl_binary_writer_write_string_fmt( writer,
"// %s can not be defined for c-usage as c do not yet support declaring the storage-type for an enum\n"
"#if defined(__cplusplus)\n", enum_info.name );

dl_binary_writer_write_string_fmt( writer, "enum %s%s\n{\n", enum_info.name, storage_decl );

dl_enum_value_info_t* values = (dl_enum_value_info_t*)malloc( enum_info.value_count * sizeof( dl_enum_value_info_t ) );
dl_reflect_get_enum_values( ctx, tids[enum_index], values, enum_info.value_count );
Expand All @@ -118,6 +139,9 @@ static void dl_context_write_c_header_enums( dl_binary_writer* writer, dl_ctx_t

free( values );
dl_binary_writer_write_string_fmt( writer, "\n};\n\n" );

if(enum_info.storage != DL_TYPE_STORAGE_ENUM_UINT32)
dl_binary_writer_write_string_fmt( writer, "#endif // defined(__cplusplus)\n");
}

free( tids );
Expand Down Expand Up @@ -199,7 +223,14 @@ static void dl_context_write_c_header_member( dl_binary_writer* writer, dl_ctx_t
dl_binary_writer_write_string_fmt( writer, " const struct %s* %s;\n", sub_type.name, member->name );
}
break;
case DL_TYPE_STORAGE_ENUM_INT8:
case DL_TYPE_STORAGE_ENUM_INT16:
case DL_TYPE_STORAGE_ENUM_INT32:
case DL_TYPE_STORAGE_ENUM_INT64:
case DL_TYPE_STORAGE_ENUM_UINT8:
case DL_TYPE_STORAGE_ENUM_UINT16:
case DL_TYPE_STORAGE_ENUM_UINT32:
case DL_TYPE_STORAGE_ENUM_UINT64:
{
dl_enum_info_t sub_type;
dl_reflect_get_enum_info( ctx, member->type_id, &sub_type );
Expand Down
11 changes: 6 additions & 5 deletions src/dl_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -220,11 +220,12 @@ struct dl_enum_value_desc

struct dl_enum_desc
{
uint32_t name;
uint32_t value_count;
uint32_t value_start;
uint32_t alias_count; /// number of aliases for this enum, always at least 1. Alias 0 is consider the "main name" of the value and need to be a valid c enum name.
uint32_t alias_start; /// offset into alias list where aliases for this enum-value start.
uint32_t name;
dl_type_storage_t storage;
uint32_t value_count;
uint32_t value_start;
uint32_t alias_count; /// number of aliases for this enum, always at least 1. Alias 0 is consider the "main name" of the value and need to be a valid c enum name.
uint32_t alias_start; /// offset into alias list where aliases for this enum-value start.
};

struct dl_enum_alias_desc
Expand Down
21 changes: 21 additions & 0 deletions tests/dl_tests_enum.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#include <gtest/gtest.h>

#include "dl_test_common.h"

static_assert(sizeof(enum_int8) == sizeof(int8_t), "size of enum is incorrect");
static_assert(sizeof(enum_int16) == sizeof(int16_t), "size of enum is incorrect");
static_assert(sizeof(enum_int32) == sizeof(int32_t), "size of enum is incorrect");
static_assert(sizeof(enum_int64) == sizeof(int64_t), "size of enum is incorrect");
static_assert(sizeof(enum_uint8) == sizeof(uint8_t), "size of enum is incorrect");
static_assert(sizeof(enum_uint16) == sizeof(uint16_t), "size of enum is incorrect");
static_assert(sizeof(enum_uint32) == sizeof(uint32_t), "size of enum is incorrect");
static_assert(sizeof(enum_uint64) == sizeof(uint64_t), "size of enum is incorrect");

static_assert(DL_ALIGNOF(enum_int8) == DL_ALIGNOF(int8_t), "size of enum is incorrect");
static_assert(DL_ALIGNOF(enum_int16) == DL_ALIGNOF(int16_t), "size of enum is incorrect");
static_assert(DL_ALIGNOF(enum_int32) == DL_ALIGNOF(int32_t), "size of enum is incorrect");
static_assert(DL_ALIGNOF(enum_int64) == DL_ALIGNOF(int64_t), "size of enum is incorrect");
static_assert(DL_ALIGNOF(enum_uint8) == DL_ALIGNOF(uint8_t), "size of enum is incorrect");
static_assert(DL_ALIGNOF(enum_uint16) == DL_ALIGNOF(uint16_t), "size of enum is incorrect");
static_assert(DL_ALIGNOF(enum_uint32) == DL_ALIGNOF(uint32_t), "size of enum is incorrect");
static_assert(DL_ALIGNOF(enum_uint64) == DL_ALIGNOF(uint64_t), "size of enum is incorrect");
7 changes: 7 additions & 0 deletions tests/dl_tests_typelib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -360,3 +360,10 @@ TEST_F( DLTypeLib, enum_in_2_tlds )
free(tl1);
free(tl2);
}

// test read-errors for enum

// invalid type

// enum that do not fit in type!

12 changes: 11 additions & 1 deletion tests/unittest.tld
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,17 @@
"MULTI_ALIAS1" : { "value" : 7, "aliases" : [ "alias1", "alias2", "alias3" ] },
"MULTI_ALIAS2" : { "value" : 8, "aliases" : [ "alias4" ] }
}
}
},

// sized enums
"enum_int8" : { "type" : "int8", "values" : { "int8_1" : 1 } },
"enum_int16" : { "type" : "int16", "values" : { "int16_1" : 1 } },
"enum_int32" : { "type" : "int32", "values" : { "int32_1" : 1 } },
"enum_int64" : { "type" : "int64", "values" : { "int64_1" : 1 } },
"enum_uint8" : { "type" : "uint8", "values" : { "uint8_1" : 1 } },
"enum_uint16" : { "type" : "uint16", "values" : { "uint16_1" : 1 } },
"enum_uint32" : { "type" : "uint32", "values" : { "uint32_1" : 1 } },
"enum_uint64" : { "type" : "uint64", "values" : { "uint64_1" : 1 } }
},

"types" : {
Expand Down

0 comments on commit c0c32c5

Please sign in to comment.