mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 03:51:18 +00:00
Use correct sizes and alignments. Fix designated initializers and literals. Added todo
This commit is contained in:
65
missing.txt
Normal file
65
missing.txt
Normal file
@@ -0,0 +1,65 @@
|
||||
Things missing:
|
||||
|
||||
* Attributes
|
||||
- All types: @noreflect
|
||||
- Struct: @packed, @aligned, @opaque
|
||||
- Enums: @distinct, @noreflect
|
||||
- Unions: @packed, @aligned, @opaque
|
||||
- Functions: @inline, @reflect, @noreturn, @section, @unused, @used, @interrupt, @naked, @convention()
|
||||
- Calls: @noinline
|
||||
- Variables, parameters: @unused
|
||||
- Constants, globals: @unused, @used, @section
|
||||
|
||||
* Designated initializer
|
||||
- Array initializer
|
||||
- Array range initializer { [1..2] = 2 }
|
||||
|
||||
* Initializers
|
||||
- Array initializers
|
||||
- Union initializers
|
||||
|
||||
* Asserts
|
||||
- assert, $assert
|
||||
- @unreachable
|
||||
|
||||
* Types
|
||||
- Vararrays
|
||||
- Strings
|
||||
- Array
|
||||
- Slice
|
||||
- Values: size, alignment, name, qualifiedName
|
||||
- Functions: offsetof
|
||||
- Distinct types
|
||||
- Simd types?
|
||||
- Complex types?
|
||||
- Subtype casts
|
||||
- Bitstruct
|
||||
- Enumset
|
||||
- Typeid
|
||||
- Union usage
|
||||
|
||||
* Expressions
|
||||
- Disallow x >= 0 and x < 0 on unsigned types unless in a macro.
|
||||
|
||||
* Switch
|
||||
- String switch
|
||||
- Range case
|
||||
|
||||
* Functions
|
||||
- Varargs
|
||||
- C ABI
|
||||
- Safe varargs
|
||||
|
||||
* Pre-post conditions
|
||||
- Breakdown here
|
||||
|
||||
* Error handling
|
||||
- Error unions
|
||||
- Catch/try
|
||||
- Function return channel
|
||||
|
||||
* Enum
|
||||
- Values: min, max, array
|
||||
- Functions: fomOrdinal, ordinal, fromName, name, fromFullName, fullName, fromQualifiedName, qualifiedName, <value>(), fromValue()
|
||||
|
||||
|
||||
@@ -2,16 +2,6 @@ module bar;
|
||||
|
||||
typedef int as Bob;
|
||||
|
||||
/* hello *//* there */
|
||||
/+ why /+ you /* lucky +/ +/
|
||||
// Whut
|
||||
// Here
|
||||
//
|
||||
//---
|
||||
/*
|
||||
Hello
|
||||
*/
|
||||
|
||||
struct Test
|
||||
{
|
||||
int a;
|
||||
@@ -38,32 +28,6 @@ struct Teob
|
||||
int oekfeo;
|
||||
}
|
||||
|
||||
typedef long as Frob;
|
||||
|
||||
enum EnumTestAlias : Frob
|
||||
{
|
||||
VALUE1 = 4,
|
||||
VALUE2
|
||||
}
|
||||
|
||||
enum EnumTestDefault
|
||||
{
|
||||
VALUE,
|
||||
VALUE2
|
||||
}
|
||||
|
||||
enum EnumTestNoOverflowAfterLong : long
|
||||
{
|
||||
VALUE = 0x7FFF_FFFF_FFFF_FFFE,
|
||||
VALUE_NO_EXCEED
|
||||
}
|
||||
|
||||
enum EnumTestSmall : ushort
|
||||
{
|
||||
VALUE = 0xFF,
|
||||
VALUE2 = 0xFFFF
|
||||
}
|
||||
|
||||
enum EnumWithData : ushort (int a, char[] x, long b = 4)
|
||||
{
|
||||
// Currently the args are ignored TODO!
|
||||
@@ -105,8 +69,8 @@ error Error
|
||||
{
|
||||
BLURB,
|
||||
NO_SUCH_FILE,
|
||||
|
||||
}
|
||||
|
||||
error OtherError
|
||||
{
|
||||
FOO_BAR
|
||||
@@ -128,6 +92,39 @@ enum Inf2 : byte
|
||||
|
||||
typedef Inf as BooInf;
|
||||
|
||||
struct TestStruct
|
||||
{
|
||||
int a;
|
||||
}
|
||||
|
||||
struct TestStruct2
|
||||
{
|
||||
TestStruct a;
|
||||
char xx;
|
||||
TestStruct b;
|
||||
int c;
|
||||
}
|
||||
|
||||
union TestUnion
|
||||
{
|
||||
int a;
|
||||
double f;
|
||||
}
|
||||
|
||||
|
||||
func TestStruct structTest(int i)
|
||||
{
|
||||
|
||||
TestUnion tu;
|
||||
/* TestStruct foo = { i };
|
||||
TestStruct foo2 = { a = i };*/
|
||||
TestStruct foo3 = TestStruct { i };
|
||||
return foo3;
|
||||
/* TestStruct2 bar = { c = 2 };
|
||||
int x = 3 * i;
|
||||
TestStruct2 bar2 = { b.a = x, a.a = x + 1 };
|
||||
return bar2;*/
|
||||
}
|
||||
func void enumInferenceTest()
|
||||
{
|
||||
OtherError e = OtherError.FOO_BAR;
|
||||
|
||||
13
resources/tests/comments_ok.c3
Normal file
13
resources/tests/comments_ok.c3
Normal file
@@ -0,0 +1,13 @@
|
||||
module comments;
|
||||
/* Span *//* style */
|
||||
|
||||
/+ Nested /+ Errors /* Inside +/ +/
|
||||
// Single line
|
||||
/*
|
||||
Multiline span style
|
||||
*/
|
||||
|
||||
func void test()
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -4,3 +4,28 @@ enum EnumTest : long
|
||||
VALUE2
|
||||
}
|
||||
|
||||
typedef long as Frob;
|
||||
|
||||
enum EnumTestAlias : Frob
|
||||
{
|
||||
VALUE1 = 4,
|
||||
VALUE2
|
||||
}
|
||||
|
||||
enum EnumTestDefault
|
||||
{
|
||||
VALUE,
|
||||
VALUE2
|
||||
}
|
||||
|
||||
enum EnumTestNoOverflowAfterLong : long
|
||||
{
|
||||
VALUE = 0x7FFF_FFFF_FFFF_FFFE,
|
||||
VALUE_NO_EXCEED
|
||||
}
|
||||
|
||||
enum EnumTestSmall : ushort
|
||||
{
|
||||
VALUE = 0xFF,
|
||||
VALUE2 = 0xFFFF
|
||||
}
|
||||
|
||||
12
resources/tests/error_decl_ok.c3
Normal file
12
resources/tests/error_decl_ok.c3
Normal file
@@ -0,0 +1,12 @@
|
||||
module errors;
|
||||
|
||||
error TheError
|
||||
{
|
||||
FOO_MISSING,
|
||||
NO_SUCH_FILE,
|
||||
}
|
||||
|
||||
error OtherError
|
||||
{
|
||||
BAR_OVERFLOWED
|
||||
}
|
||||
0
resources/tests/structs_ok.c3
Normal file
0
resources/tests/structs_ok.c3
Normal file
5
resources/tests/typedef_errors.c3
Normal file
5
resources/tests/typedef_errors.c3
Normal file
@@ -0,0 +1,5 @@
|
||||
module typedefs;
|
||||
|
||||
typedef Loop as Loop2;
|
||||
typedef Loop2 as Loop3;
|
||||
typedef Loop3 as Loop;
|
||||
14
resources/tests/typedefs_ok.c3
Normal file
14
resources/tests/typedefs_ok.c3
Normal file
@@ -0,0 +1,14 @@
|
||||
module typedefs;
|
||||
|
||||
// Standard case
|
||||
typedef int as Foo;
|
||||
|
||||
// Nested resolution
|
||||
typedef AType as BType;
|
||||
typedef int as AType;
|
||||
|
||||
enum Bar : BType
|
||||
{
|
||||
A,
|
||||
B
|
||||
}
|
||||
@@ -551,12 +551,6 @@ void fprint_expr_recursive(FILE *file, Expr *expr, int indent)
|
||||
fprint_expr_common(file, expr, indent + 1);
|
||||
fprint_type_info_recursive(file, expr->type_access.type, indent + 1);
|
||||
break;
|
||||
case EXPR_STRUCT_VALUE:
|
||||
fprintf_indented(file, indent, "(structvalue\n");
|
||||
fprint_expr_common(file, expr, indent + 1);
|
||||
fprint_type_info_recursive(file, expr->struct_value_expr.type, indent + 1);
|
||||
fprint_expr_recursive(file, expr->struct_value_expr.init_expr, indent + 1);
|
||||
break;
|
||||
case EXPR_ACCESS:
|
||||
fprintf_indented(file, indent, "(access .%s\n", expr->access_expr.sub_element.string);
|
||||
fprint_expr_common(file, expr, indent + 1);
|
||||
@@ -595,12 +589,27 @@ void fprint_expr_recursive(FILE *file, Expr *expr, int indent)
|
||||
fprint_expr_recursive(file, expr->ternary_expr.else_expr, indent + 1);
|
||||
break;
|
||||
case EXPR_INITIALIZER_LIST:
|
||||
fprintf_indented(file, indent, "(initializerlist\n");
|
||||
fprintf_indented(file, indent, "(initializerlist ");
|
||||
switch (expr->expr_initializer.init_type)
|
||||
{
|
||||
case INITIALIZER_UNKNOWN:
|
||||
fprintf(file, "not-analyzed\n");
|
||||
break;
|
||||
case INITIALIZER_ZERO:
|
||||
fprintf(file, "zero\n");
|
||||
break;
|
||||
case INITIALIZER_NORMAL:
|
||||
fprintf(file, "normal\n");
|
||||
break;
|
||||
case INITIALIZER_DESIGNATED:
|
||||
fprintf(file, "designated\n");
|
||||
break;
|
||||
}
|
||||
fprint_expr_common(file, expr, indent + 1);
|
||||
{
|
||||
VECEACH(expr->initializer_expr, i)
|
||||
VECEACH(expr->expr_initializer.initializer_expr, i)
|
||||
{
|
||||
fprint_expr_recursive(file, expr->initializer_expr[i], indent + 1);
|
||||
fprint_expr_recursive(file, expr->expr_initializer.initializer_expr[i], indent + 1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -137,7 +137,7 @@ typedef struct
|
||||
{
|
||||
unsigned char bitsize;
|
||||
unsigned char bytesize;
|
||||
unsigned char min_alignment;
|
||||
unsigned char abi_alignment;
|
||||
unsigned char pref_alignment;
|
||||
} TypeBuiltin;
|
||||
|
||||
@@ -226,7 +226,7 @@ typedef struct
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t alignment;
|
||||
uint32_t abi_alignment;
|
||||
uint64_t size;
|
||||
Decl **members;
|
||||
} StructDecl;
|
||||
@@ -500,6 +500,32 @@ typedef struct
|
||||
Ast **stmts;
|
||||
} ExprFuncBlock;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
INITIALIZER_UNKNOWN,
|
||||
INITIALIZER_ZERO,
|
||||
INITIALIZER_DESIGNATED,
|
||||
INITIALIZER_NORMAL
|
||||
} InitializerType;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
InitializerType init_type;
|
||||
Expr** initializer_expr;
|
||||
} ExprInitializer;
|
||||
|
||||
typedef struct _DesignatedInitPath
|
||||
{
|
||||
Decl *decl;
|
||||
struct _DesignatedInitPath *sub_path;
|
||||
} DesignatedInitPath;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
DesignatedInitPath path;
|
||||
Expr *value;
|
||||
} ExprDesignatedInit;
|
||||
|
||||
struct _Expr
|
||||
{
|
||||
ExprKind expr_kind : 8;
|
||||
@@ -507,6 +533,7 @@ struct _Expr
|
||||
SourceRange span;
|
||||
Type *type;
|
||||
union {
|
||||
ExprDesignatedInit designated_init_expr;
|
||||
ExprCast cast_expr;
|
||||
ExprConst const_expr;
|
||||
ExprStructValue struct_value_expr;
|
||||
@@ -522,7 +549,7 @@ struct _Expr
|
||||
ExprAccess access_expr;
|
||||
ExprIdentifier identifier_expr;
|
||||
ExprType type_expr;
|
||||
Expr** initializer_expr;
|
||||
ExprInitializer expr_initializer;
|
||||
Expr** expression_list;
|
||||
ExprScope expr_scope;
|
||||
ExprFuncBlock expr_block;
|
||||
@@ -1133,6 +1160,7 @@ bool type_is_subtype(Type *type, Type *possible_subtype);
|
||||
Type *type_find_common_ancestor(Type *left, Type *right);
|
||||
const char *type_to_error_string(Type *type);
|
||||
size_t type_size(Type *canonical);
|
||||
size_t type_abi_alignment(Type *canonical);
|
||||
void type_append_signature_name(Type *type, char *dst, size_t *offset);
|
||||
Type *type_find_max_type(Type *type, Type *other);
|
||||
|
||||
|
||||
@@ -223,14 +223,13 @@ typedef enum
|
||||
EXPR_SIZEOF,
|
||||
EXPR_SUBSCRIPT,
|
||||
EXPR_ACCESS,
|
||||
EXPR_STRUCT_VALUE,
|
||||
EXPR_STRUCT_INIT_VALUES,
|
||||
EXPR_INITIALIZER_LIST,
|
||||
EXPR_EXPRESSION_LIST,
|
||||
EXPR_CAST,
|
||||
EXPR_SCOPED_EXPR,
|
||||
EXPR_MACRO_EXPR,
|
||||
EXPR_EXPR_BLOCK,
|
||||
EXPR_DESIGNATED_INIT,
|
||||
} ExprKind;
|
||||
|
||||
|
||||
|
||||
@@ -101,12 +101,11 @@ LLVMValueRef gencontext_emit_address(GenContext *context, Expr *expr)
|
||||
case EXPR_POST_UNARY:
|
||||
case EXPR_TYPE_ACCESS:
|
||||
case EXPR_CALL:
|
||||
case EXPR_STRUCT_VALUE:
|
||||
case EXPR_STRUCT_INIT_VALUES:
|
||||
case EXPR_INITIALIZER_LIST:
|
||||
case EXPR_EXPRESSION_LIST:
|
||||
case EXPR_CAST:
|
||||
case EXPR_MACRO_EXPR:
|
||||
case EXPR_DESIGNATED_INIT:
|
||||
UNREACHABLE
|
||||
}
|
||||
UNREACHABLE
|
||||
@@ -740,30 +739,55 @@ static inline LLVMValueRef gencontext_emit_expression_list_expr(GenContext *cont
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static inline LLVMValueRef gencontext_emit_initializer_list_expr(GenContext *context, Expr *expr)
|
||||
{
|
||||
LLVMTypeRef type = llvm_type(expr->type);
|
||||
LLVMValueRef value = LLVMGetUndef(type);
|
||||
|
||||
if (!vec_size(expr->initializer_expr))
|
||||
if (expr->expr_initializer.init_type == INITIALIZER_ZERO)
|
||||
{
|
||||
LLVMValueRef ref = gencontext_emit_alloca(context, type, "temp");
|
||||
value = LLVMBuildMemSet(context->builder, ref, LLVMConstInt(llvm_type(type_byte), 0, false),
|
||||
LLVMConstInt(llvm_type(type_ulong), expr->type->decl->strukt.size, false), expr->type->decl->strukt.alignment);
|
||||
return ref;
|
||||
LLVMConstInt(llvm_type(type_ulong), expr->type->decl->strukt.size, false), expr->type->decl->strukt.abi_alignment);
|
||||
return value;
|
||||
}
|
||||
|
||||
VECEACH(expr->initializer_expr, i)
|
||||
Expr **elements = expr->expr_initializer.initializer_expr;
|
||||
|
||||
if (expr->expr_initializer.init_type == INITIALIZER_NORMAL)
|
||||
{
|
||||
LLVMValueRef init_value = gencontext_emit_expr(context, expr->initializer_expr[i]);
|
||||
value = LLVMBuildInsertValue(context->builder, value, init_value, i, "literal");
|
||||
VECEACH(elements, i)
|
||||
{
|
||||
LLVMValueRef init_value = gencontext_emit_expr(context, elements[i]);
|
||||
value = LLVMBuildInsertValue(context->builder, value, init_value, i, "literal");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
static inline LLVMValueRef gencontext_emit_struct_init_values_expr(GenContext *context, Expr *expr)
|
||||
{
|
||||
TODO
|
||||
LLVMValueRef ref = gencontext_emit_alloca(context, type, "temp");
|
||||
value = LLVMBuildMemSet(context->builder, ref, LLVMConstInt(llvm_type(type_byte), 0, false),
|
||||
LLVMConstInt(llvm_type(type_ulong), expr->type->decl->strukt.size, false), expr->type->decl->strukt.abi_alignment);
|
||||
|
||||
VECEACH(elements, i)
|
||||
{
|
||||
Expr *element = elements[i];
|
||||
LLVMValueRef sub_value = gencontext_emit_expr(context, element->designated_init_expr.value);
|
||||
Decl *parent = expr->type->decl;
|
||||
DesignatedInitPath *path = &element->designated_init_expr.path;
|
||||
LLVMValueRef subref = ref;
|
||||
assert(element->expr_kind == EXPR_DESIGNATED_INIT);
|
||||
while (path)
|
||||
{
|
||||
subref = LLVMBuildStructGEP2(context->builder, llvm_type(parent->type), subref, path->decl->var.id, "access");
|
||||
parent = path->decl;
|
||||
path = path->sub_path;
|
||||
}
|
||||
LLVMBuildStore(context->builder, sub_value, subref);
|
||||
}
|
||||
|
||||
return ref;
|
||||
}
|
||||
|
||||
static inline LLVMValueRef gencontext_emit_expr_block(GenContext *context, Expr *expr)
|
||||
@@ -803,6 +827,9 @@ LLVMValueRef gencontext_emit_expr(GenContext *context, Expr *expr)
|
||||
{
|
||||
case EXPR_POISONED:
|
||||
UNREACHABLE
|
||||
case EXPR_DESIGNATED_INIT:
|
||||
// This is handled inside of initializer setup
|
||||
UNREACHABLE
|
||||
case EXPR_EXPR_BLOCK:
|
||||
return gencontext_emit_expr_block(context, expr);
|
||||
case EXPR_SCOPED_EXPR:
|
||||
@@ -831,10 +858,6 @@ LLVMValueRef gencontext_emit_expr(GenContext *context, Expr *expr)
|
||||
return gencontext_emit_call_expr(context, expr);
|
||||
case EXPR_ACCESS:
|
||||
return gencontext_emit_access_expr(context, expr);
|
||||
case EXPR_STRUCT_VALUE:
|
||||
return gencontext_emit_struct_value_expr(context, expr);
|
||||
case EXPR_STRUCT_INIT_VALUES:
|
||||
return gencontext_emit_struct_init_values_expr(context, expr);
|
||||
case EXPR_INITIALIZER_LIST:
|
||||
return gencontext_emit_initializer_list_expr(context, expr);
|
||||
case EXPR_EXPRESSION_LIST:
|
||||
|
||||
@@ -44,11 +44,11 @@ static LLVMValueRef gencontext_emit_decl(GenContext *context, Ast *ast)
|
||||
{
|
||||
Expr *expr = decl->var.init_expr;
|
||||
// Quick path for empty initializer list
|
||||
if (expr->expr_kind == EXPR_INITIALIZER_LIST && vec_size(expr->initializer_expr) == 0)
|
||||
if (expr->expr_kind == EXPR_INITIALIZER_LIST && expr->expr_initializer.init_type == INITIALIZER_ZERO)
|
||||
{
|
||||
LLVMBuildMemSet(context->builder, decl->var.backend_ref, LLVMConstInt(llvm_type(type_byte), 0, false),
|
||||
LLVMConstInt(llvm_type(type_ulong), expr->type->decl->strukt.size, false),
|
||||
expr->type->decl->strukt.alignment);
|
||||
expr->type->decl->strukt.abi_alignment);
|
||||
return decl->var.backend_ref;
|
||||
}
|
||||
|
||||
|
||||
@@ -226,5 +226,5 @@ void llvm_set_struct_size_alignment(Decl *decl)
|
||||
{
|
||||
LLVMTypeRef type = llvm_get_type(LLVMGetGlobalContext(), decl->type);
|
||||
decl->strukt.size = LLVMStoreSizeOfType(target_data_layout(), type);
|
||||
decl->strukt.alignment = LLVMPreferredAlignmentOfType(target_data_layout(), type);
|
||||
decl->strukt.abi_alignment = LLVMPreferredAlignmentOfType(target_data_layout(), type);
|
||||
}
|
||||
|
||||
@@ -249,8 +249,9 @@ Expr *parse_initializer(Context *context)
|
||||
Expr *parse_initializer_list(Context *context)
|
||||
{
|
||||
Expr *initializer_list = EXPR_NEW_TOKEN(EXPR_INITIALIZER_LIST, context->tok);
|
||||
initializer_list->expr_initializer.init_type = INITIALIZER_UNKNOWN;
|
||||
CONSUME_OR(TOKEN_LBRACE, &poisoned_expr);
|
||||
if (!parse_param_list(context, &initializer_list->initializer_expr, false)) return &poisoned_expr;
|
||||
if (!parse_param_list(context, &initializer_list->expr_initializer.initializer_expr, false)) return &poisoned_expr;
|
||||
CONSUME_OR(TOKEN_RBRACE, &poisoned_expr);
|
||||
return initializer_list;
|
||||
}
|
||||
|
||||
@@ -1033,7 +1033,9 @@ bool parse_struct_body(Context *context, Decl *parent, Decl *visible_parent)
|
||||
decl_poison(other);
|
||||
decl_poison(member);
|
||||
}
|
||||
unsigned index = vec_size(parent->strukt.members);
|
||||
parent->strukt.members = VECADD(parent->strukt.members, member);
|
||||
member->var.id = index;
|
||||
advance(context);
|
||||
if (context->tok.type != TOKEN_COMMA) break;
|
||||
}
|
||||
@@ -1994,11 +1996,7 @@ Expr *parse_type_identifier_with_path(Context *context, Path *path)
|
||||
RANGE_EXTEND_PREV(type);
|
||||
if (context->tok.type == TOKEN_LBRACE)
|
||||
{
|
||||
Expr *expr = EXPR_NEW_TOKEN(EXPR_STRUCT_VALUE, context->tok);
|
||||
expr->struct_value_expr.type = type;
|
||||
expr->struct_value_expr.init_expr = TRY_EXPR_OR(parse_initializer_list(context), &poisoned_expr);
|
||||
|
||||
return expr;
|
||||
return TRY_EXPR_OR(parse_initializer_list(context), &poisoned_expr);
|
||||
}
|
||||
EXPECT_OR(TOKEN_DOT, &poisoned_expr);
|
||||
return parse_type_access(context, type);
|
||||
|
||||
@@ -40,6 +40,8 @@ static inline bool sema_analyse_error(Context *context __unused, Decl *decl)
|
||||
|
||||
static inline bool sema_analyse_struct_member(Context *context, Decl *decl)
|
||||
{
|
||||
assert(decl->resolve_status == RESOLVE_NOT_DONE);
|
||||
decl->resolve_status = RESOLVE_RUNNING;
|
||||
if (decl->decl_kind == DECL_STRUCT || decl->decl_kind == DECL_UNION)
|
||||
{
|
||||
DEBUG_LOG("Beginning analysis of inner struct/union");
|
||||
@@ -74,6 +76,7 @@ static inline bool sema_analyse_struct_member(Context *context, Decl *decl)
|
||||
}
|
||||
decl->type = decl->var.type_info->type;
|
||||
assert(decl->var.type_info->type);
|
||||
decl->resolve_status = RESOLVE_DONE;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -430,6 +433,52 @@ static inline bool sema_analyse_generic(Context *context, Decl *decl)
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void sema_set_struct_size(Decl *decl)
|
||||
{
|
||||
// TODO packed
|
||||
uint64_t size = 0;
|
||||
uint64_t alignment = 0;
|
||||
VECEACH(decl->strukt.members, i)
|
||||
{
|
||||
Decl *member = decl->strukt.members[i];
|
||||
Type *canonical = member->type->canonical;
|
||||
uint64_t member_size = type_size(canonical);
|
||||
uint64_t member_alignment = type_abi_alignment(canonical);
|
||||
assert(member_size > 0);
|
||||
// Add padding.
|
||||
if (member_alignment && (size % member_alignment))
|
||||
{
|
||||
size += member_alignment - size % member_alignment;
|
||||
}
|
||||
// Add size.
|
||||
size += member_size;
|
||||
if (member_alignment > alignment) alignment = member_alignment;
|
||||
}
|
||||
decl->strukt.abi_alignment = alignment;
|
||||
if (alignment && size % alignment)
|
||||
{
|
||||
size += alignment - size % alignment;
|
||||
}
|
||||
decl->strukt.size = size;
|
||||
}
|
||||
|
||||
static inline void sema_set_union_size(Decl *decl)
|
||||
{
|
||||
uint64_t size = 0;
|
||||
uint64_t alignment = 0;
|
||||
VECEACH(decl->strukt.members, i)
|
||||
{
|
||||
Decl *member = decl->strukt.members[i];
|
||||
Type *canonical = member->type->canonical;
|
||||
uint64_t member_size = type_size(canonical);
|
||||
uint64_t member_alignment = type_abi_alignment(canonical);
|
||||
if (member_size > size) size = member_size;
|
||||
if (member_alignment > alignment) alignment = member_alignment;
|
||||
}
|
||||
decl->strukt.abi_alignment = alignment;
|
||||
decl->strukt.size = size;
|
||||
}
|
||||
|
||||
bool sema_analyse_decl(Context *context, Decl *decl)
|
||||
{
|
||||
if (decl->resolve_status == RESOLVE_DONE) return decl_ok(decl);
|
||||
@@ -450,9 +499,13 @@ bool sema_analyse_decl(Context *context, Decl *decl)
|
||||
if (!sema_analyse_throws(context, decl)) return decl_poison(decl);
|
||||
break;
|
||||
case DECL_STRUCT:
|
||||
if (!sema_analyse_struct_union(context, decl)) return decl_poison(decl);
|
||||
sema_set_struct_size(decl);
|
||||
decl_set_external_name(decl);
|
||||
break;
|
||||
case DECL_UNION:
|
||||
if (!sema_analyse_struct_union(context, decl)) return decl_poison(decl);
|
||||
llvm_set_struct_size_alignment(decl);
|
||||
sema_set_union_size(decl);
|
||||
decl_set_external_name(decl);
|
||||
break;
|
||||
case DECL_FUNC:
|
||||
|
||||
@@ -280,15 +280,6 @@ static inline bool sema_expr_analyse_call(Context *context, Type *to, Expr *expr
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool sema_expr_analyse_struct_value(Context *context, Type *to, Expr *expr)
|
||||
{
|
||||
TODO
|
||||
}
|
||||
|
||||
static inline bool sema_expr_analyse_struct_init_values(Context *context, Type *to, Expr *expr)
|
||||
{
|
||||
TODO
|
||||
}
|
||||
|
||||
static inline bool sema_expr_analyse_subscript(Context *context, Type *to, Expr *expr)
|
||||
{
|
||||
@@ -492,6 +483,7 @@ static Decl *sema_analyse_init_identifier(Context *context, Decl *strukt, Expr *
|
||||
expr->resolve_status = RESOLVE_RUNNING;
|
||||
expr->identifier_expr.decl = sema_analyse_init_identifier_string(context, strukt, expr->identifier_expr.identifier);
|
||||
expr->resolve_status = RESOLVE_DONE;
|
||||
expr->type = expr->identifier_expr.decl->type;
|
||||
return expr->identifier_expr.decl;
|
||||
}
|
||||
|
||||
@@ -507,6 +499,7 @@ static Decl *sema_analyse_init_access(Context *context, Decl *strukt, Expr *acce
|
||||
}
|
||||
decl = access_expr->access_expr.ref = sema_analyse_init_identifier_string(context, decl->type->decl, access_expr->access_expr.sub_element.string);
|
||||
access_expr->resolve_status = RESOLVE_DONE;
|
||||
access_expr->type = decl->type;
|
||||
return decl;
|
||||
}
|
||||
|
||||
@@ -534,74 +527,189 @@ static Decl *sema_analyse_init_path(Context *context, Decl *strukt, Expr *expr)
|
||||
}
|
||||
}
|
||||
|
||||
static bool sema_expr_analyse_designated_init(Context *context, DesignatedInitPath *path, Decl *top, Expr *path_expr);
|
||||
|
||||
typedef enum
|
||||
static bool sema_expr_analyse_designated_init_ident(Context *context, DesignatedInitPath *path, Decl *top, const char *name)
|
||||
{
|
||||
INIT_SEMA_ERROR,
|
||||
INIT_SEMA_NOT_FOUND,
|
||||
INIT_SEMA_OK
|
||||
} InitSemaResult;
|
||||
|
||||
static InitSemaResult sema_expr_analyse_struct_named_initializer_list(Context *context, Decl *assigned, Expr *expr_list)
|
||||
{
|
||||
VECEACH(expr_list->initializer_expr, i)
|
||||
// 3. Loop through the members.
|
||||
Decl **members = top->strukt.members;
|
||||
VECEACH(members, i)
|
||||
{
|
||||
Expr *expr = expr_list->initializer_expr[i];
|
||||
Decl *member = members[i];
|
||||
if (member->name == name)
|
||||
{
|
||||
// 4. If found, set this to the current path.
|
||||
(*path) = (DesignatedInitPath) { .decl = member, .sub_path = NULL };
|
||||
|
||||
// 5. And we're done!
|
||||
return true;
|
||||
}
|
||||
// 6. We might encounter anonymous members. Treat this as a possible "match"
|
||||
if (!member->name)
|
||||
{
|
||||
DesignatedInitPath anon_path;
|
||||
bool found = sema_expr_analyse_designated_init_ident(context, &anon_path, member, name);
|
||||
if (found)
|
||||
{
|
||||
// 7. If found, create a copy path.
|
||||
DesignatedInitPath *path_copy = malloc_arena(sizeof(DesignatedInitPath));
|
||||
*path_copy = anon_path;
|
||||
(*path) = (DesignatedInitPath) { .decl = member, .sub_path = path_copy };
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
static bool sema_expr_analyse_designated_init(Context *context, DesignatedInitPath *path, Decl *top, Expr *path_expr)
|
||||
{
|
||||
// Our expression will look like this for a.b[3].c = ...
|
||||
// access(subscript(access(identifier))), now we need to reverse that.
|
||||
switch (path_expr->expr_kind)
|
||||
{
|
||||
case EXPR_IDENTIFIER:
|
||||
|
||||
// Resolving for an identifier:
|
||||
// 1. Can't be a path attached.
|
||||
if (path_expr->identifier_expr.path) return false;
|
||||
|
||||
// 2. Ensure it's a union or struct
|
||||
if (!decl_is_struct_type(top)) return false;
|
||||
|
||||
return sema_expr_analyse_designated_init_ident(context, path, top, path_expr->identifier_expr.identifier);
|
||||
|
||||
case EXPR_ACCESS:
|
||||
|
||||
// Resolve for access:
|
||||
|
||||
// 1. Resolve the parent path:
|
||||
if (!sema_expr_analyse_designated_init(context, path, top, path_expr->access_expr.parent)) return false;
|
||||
|
||||
// 2. Our new top is now lowest init path.
|
||||
while (path->sub_path)
|
||||
{
|
||||
path = path->sub_path;
|
||||
}
|
||||
top = path->decl;
|
||||
|
||||
// 3. Do an analysis with the identifier:
|
||||
path->sub_path = malloc_arena(sizeof(DesignatedInitPath));
|
||||
return sema_expr_analyse_designated_init_ident(context,
|
||||
path->sub_path,
|
||||
top->type->decl,
|
||||
path_expr->access_expr.sub_element.string);
|
||||
case EXPR_SUBSCRIPT:
|
||||
|
||||
// Resolve for subscript:
|
||||
|
||||
// 1. Resolve the parent path:
|
||||
if (!sema_expr_analyse_designated_init(context, path, top, path_expr->subscript_expr.expr)) return false;
|
||||
|
||||
// 2. Our new top is now lowest init path.
|
||||
while (path->sub_path)
|
||||
{
|
||||
path = path->sub_path;
|
||||
}
|
||||
top = path->decl;
|
||||
|
||||
TODO // Analyse index etc.
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool sema_expr_analyse_struct_designated_initializer_list(Context *context, Decl *assigned, Expr *expr_list)
|
||||
{
|
||||
assert(expr_list->expr_initializer.init_type == INITIALIZER_UNKNOWN);
|
||||
VECEACH(expr_list->expr_initializer.initializer_expr, i)
|
||||
{
|
||||
Expr *expr = expr_list->expr_initializer.initializer_expr[i];
|
||||
if (expr->expr_kind != EXPR_BINARY && expr->binary_expr.operator != BINARYOP_ASSIGN)
|
||||
{
|
||||
if (i != 0)
|
||||
{
|
||||
SEMA_ERROR(expr, "Named and non-named initializers are not allowed together, please choose one or the other.");
|
||||
return INIT_SEMA_ERROR;
|
||||
return false;
|
||||
}
|
||||
// If there is an unexpected expression and no previous element then this is a normal initializer list.
|
||||
return INIT_SEMA_NOT_FOUND;
|
||||
expr_list->expr_initializer.init_type = INITIALIZER_NORMAL;
|
||||
return true;
|
||||
}
|
||||
Expr *path = expr->binary_expr.left;
|
||||
Expr *path_expr = expr->binary_expr.left;
|
||||
Expr *value = expr->binary_expr.right;
|
||||
Decl *result = sema_analyse_init_path(context, assigned, path);
|
||||
if (!result)
|
||||
DesignatedInitPath path;
|
||||
if (!sema_expr_analyse_designated_init(context, &path, assigned, path_expr))
|
||||
{
|
||||
if (i != 0)
|
||||
{
|
||||
SEMA_ERROR(path, "Unexpected element when initializing '%s', did you get the name right?", assigned->name);
|
||||
return INIT_SEMA_ERROR;
|
||||
SEMA_ERROR(path_expr, "Unexpected element when initializing '%s', did you get the name right?", assigned->name);
|
||||
return false;
|
||||
}
|
||||
return INIT_SEMA_NOT_FOUND;
|
||||
expr_list->expr_initializer.init_type = INITIALIZER_NORMAL;
|
||||
return true;
|
||||
}
|
||||
if (!sema_analyse_expr_of_required_type(context, result->type, value)) return INIT_SEMA_ERROR;
|
||||
// Walk down to the last decl.
|
||||
DesignatedInitPath *init_path = &path;
|
||||
while (init_path->sub_path) init_path = init_path->sub_path;
|
||||
|
||||
if (!sema_analyse_expr_of_required_type(context, init_path->decl->type, value)) return false;
|
||||
|
||||
// Destruct the expression and replace.
|
||||
expr->designated_init_expr.value = value; // Do this first!
|
||||
expr->resolve_status = RESOLVE_DONE;
|
||||
expr->designated_init_expr.path = path;
|
||||
expr->expr_kind = EXPR_DESIGNATED_INIT;
|
||||
expr->type = init_path->decl->type;
|
||||
}
|
||||
return INIT_SEMA_OK;
|
||||
expr_list->expr_initializer.init_type = INITIALIZER_DESIGNATED;
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool sema_expr_analyse_struct_initializer_list(Context *context, Type *assigned, Expr *expr)
|
||||
{
|
||||
expr->type = assigned;
|
||||
|
||||
Decl **members = assigned->decl->strukt.members;
|
||||
unsigned size = vec_size(members);
|
||||
// Zero size init will initialize to empty.
|
||||
if (size == 0) return true;
|
||||
|
||||
InitSemaResult result = sema_expr_analyse_struct_named_initializer_list(context, assigned->decl, expr);
|
||||
if (result == INIT_SEMA_ERROR) return false;
|
||||
if (result == INIT_SEMA_OK)
|
||||
// Zero size init will initialize to empty.
|
||||
if (size == 0)
|
||||
{
|
||||
TODO
|
||||
expr->expr_initializer.init_type = INITIALIZER_ZERO;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!sema_expr_analyse_struct_designated_initializer_list(context, assigned->decl, expr)) return false;
|
||||
|
||||
// If we already parsed this.
|
||||
if (expr->expr_initializer.init_type == INITIALIZER_DESIGNATED) return true;
|
||||
|
||||
Expr **elements = expr->expr_initializer.initializer_expr;
|
||||
|
||||
assert(expr->expr_initializer.init_type == INITIALIZER_NORMAL);
|
||||
|
||||
if (assigned->type_kind == TYPE_UNION)
|
||||
{
|
||||
SEMA_ERROR(expr->initializer_expr[0], "Initializer list for unions must use named initializers, e.g. { a = 4 }");
|
||||
SEMA_ERROR(elements[0], "Initializer list for unions must use named initializers, e.g. { a = 4 }");
|
||||
return false;
|
||||
}
|
||||
if (size < vec_size(expr->initializer_expr))
|
||||
|
||||
VECEACH(elements, i)
|
||||
{
|
||||
SEMA_ERROR(expr->initializer_expr[size], "Too many elements in initializer, expected only %d.", size);
|
||||
if (i >= size)
|
||||
{
|
||||
SEMA_ERROR(elements[size], "Too many elements in initializer, expected only %d.", size);
|
||||
return false;
|
||||
}
|
||||
if (!sema_analyse_expr_of_required_type(context, members[i]->type, elements[i])) return false;
|
||||
}
|
||||
|
||||
if (size > vec_size(elements))
|
||||
{
|
||||
SEMA_ERROR(elements[vec_size(elements) - 1], "Too few elements in initializer, expected %d.", size);
|
||||
return false;
|
||||
}
|
||||
VECEACH(expr->initializer_expr, i)
|
||||
{
|
||||
if (!sema_analyse_expr_of_required_type(context, members[i]->type, expr->initializer_expr[i])) return false;
|
||||
}
|
||||
expr->type = assigned;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1910,6 +2018,7 @@ static Expr *expr_shallow_copy(Expr *source)
|
||||
return copy;
|
||||
}
|
||||
|
||||
|
||||
static Expr **expr_copy_expr_list_from_macro(Context *context, Expr *macro, Expr **expr_list);
|
||||
static Expr *expr_copy_from_macro(Context *context, Expr *macro, Expr *source_expr);
|
||||
static Ast *ast_copy_from_macro(Context *context, Expr *macro, Ast *source);
|
||||
@@ -1968,6 +2077,9 @@ static Expr *expr_copy_from_macro(Context *context, Expr *macro, Expr *source_ex
|
||||
Expr *expr = expr_shallow_copy(source_expr);
|
||||
switch (source_expr->expr_kind)
|
||||
{
|
||||
case EXPR_DESIGNATED_INIT:
|
||||
// This type of expression is only created after analysis.
|
||||
UNREACHABLE
|
||||
case EXPR_EXPR_BLOCK:
|
||||
ast_copy_list_from_macro(context, macro, &expr->expr_block.stmts);
|
||||
return expr;
|
||||
@@ -2017,15 +2129,8 @@ static Expr *expr_copy_from_macro(Context *context, Expr *macro, Expr *source_ex
|
||||
case EXPR_ACCESS:
|
||||
EXPR_COPY(expr->access_expr.parent);
|
||||
return expr;
|
||||
case EXPR_STRUCT_VALUE:
|
||||
expr->struct_value_expr.type = type_info_copy_from_macro(context, macro, expr->struct_value_expr.type);
|
||||
EXPR_COPY(expr->struct_value_expr.init_expr);
|
||||
return expr;
|
||||
case EXPR_STRUCT_INIT_VALUES:
|
||||
TODO
|
||||
return expr;
|
||||
case EXPR_INITIALIZER_LIST:
|
||||
expr->initializer_expr = expr_copy_expr_list_from_macro(context, macro, expr->initializer_expr);
|
||||
expr->expr_initializer.initializer_expr = expr_copy_expr_list_from_macro(context, macro, expr->expr_initializer.initializer_expr);
|
||||
return expr;
|
||||
case EXPR_EXPRESSION_LIST:
|
||||
expr->expression_list = expr_copy_expr_list_from_macro(context, macro, expr->expression_list);
|
||||
@@ -2426,6 +2531,7 @@ static inline bool sema_analyse_expr_dispatch(Context *context, Type *to, Expr *
|
||||
case EXPR_POISONED:
|
||||
return false;
|
||||
case EXPR_SCOPED_EXPR:
|
||||
case EXPR_DESIGNATED_INIT:
|
||||
UNREACHABLE
|
||||
case EXPR_EXPR_BLOCK:
|
||||
return sema_expr_analyse_expr_block(context, to, expr);
|
||||
@@ -2457,10 +2563,6 @@ static inline bool sema_analyse_expr_dispatch(Context *context, Type *to, Expr *
|
||||
return sema_expr_analyse_subscript(context, to, expr);
|
||||
case EXPR_ACCESS:
|
||||
return sema_expr_analyse_access(context, to, expr);
|
||||
case EXPR_STRUCT_VALUE:
|
||||
return sema_expr_analyse_struct_value(context, to, expr);
|
||||
case EXPR_STRUCT_INIT_VALUES:
|
||||
return sema_expr_analyse_struct_init_values(context, to, expr);
|
||||
case EXPR_INITIALIZER_LIST:
|
||||
return sema_expr_analyse_initializer_list(context, to, expr);
|
||||
case EXPR_CAST:
|
||||
|
||||
@@ -109,6 +109,7 @@ void target_setup()
|
||||
LLVMTypeRef float_type = LLVMFloatType();
|
||||
LLVMTypeRef double_type = LLVMDoubleType();
|
||||
LLVMTypeRef quad_type = LLVMFP128Type();
|
||||
LLVMTypeRef pointer_type = LLVMPointerType(int_type, 0);
|
||||
build_target.align_byte = LLVMABIAlignmentOfType(build_target.llvm_data_layout, byte_type);
|
||||
build_target.align_short = LLVMABIAlignmentOfType(build_target.llvm_data_layout, short_type);
|
||||
build_target.align_int = LLVMABIAlignmentOfType(build_target.llvm_data_layout, int_type);
|
||||
@@ -116,6 +117,7 @@ void target_setup()
|
||||
build_target.align_f128 = LLVMABIAlignmentOfType(build_target.llvm_data_layout, quad_type);
|
||||
build_target.align_double = LLVMABIAlignmentOfType(build_target.llvm_data_layout, double_type);
|
||||
build_target.align_float = LLVMABIAlignmentOfType(build_target.llvm_data_layout, float_type);
|
||||
build_target.align_pointer = LLVMABIAlignmentOfType(build_target.llvm_data_layout, pointer_type);
|
||||
build_target.little_endian = LLVMByteOrder(build_target.llvm_data_layout) == LLVMLittleEndian;
|
||||
build_target.width_c_short = os_target_c_type_bits(build_target.os, build_target.arch, CTYPE_SHORT);
|
||||
build_target.width_c_int = os_target_c_type_bits(build_target.os, build_target.arch, CTYPE_INT);
|
||||
|
||||
@@ -151,15 +151,15 @@ typedef struct
|
||||
bool asm_supported;
|
||||
bool float_128;
|
||||
bool float_16;
|
||||
unsigned align_min_pointer;
|
||||
unsigned align_min_byte;
|
||||
unsigned align_min_short;
|
||||
unsigned align_min_int;
|
||||
unsigned align_min_long;
|
||||
unsigned align_min_half;
|
||||
unsigned align_min_float;
|
||||
unsigned align_min_double;
|
||||
unsigned align_min_f128;
|
||||
unsigned align_pref_pointer;
|
||||
unsigned align_pref_byte;
|
||||
unsigned align_pref_short;
|
||||
unsigned align_pref_int;
|
||||
unsigned align_pref_long;
|
||||
unsigned align_pref_half;
|
||||
unsigned align_pref_float;
|
||||
unsigned align_pref_double;
|
||||
unsigned align_pref_f128;
|
||||
unsigned align_pointer;
|
||||
unsigned align_byte;
|
||||
unsigned align_short;
|
||||
|
||||
@@ -198,29 +198,18 @@ size_t type_size(Type *canonical)
|
||||
case TYPE_META_TYPE:
|
||||
return 0;
|
||||
case TYPE_ENUM:
|
||||
return type_size(canonical->decl->enums.type_info->type->canonical);
|
||||
return canonical->decl->enums.type_info->type->canonical->builtin.bytesize;
|
||||
case TYPE_ERROR:
|
||||
return type_error->canonical->builtin.bytesize;
|
||||
case TYPE_STRUCT:
|
||||
case TYPE_UNION:
|
||||
case TYPE_ERROR:
|
||||
TODO
|
||||
return canonical->decl->strukt.size;
|
||||
case TYPE_VOID:
|
||||
return 1;
|
||||
case TYPE_BOOL:
|
||||
case TYPE_I8:
|
||||
case TYPE_I16:
|
||||
case TYPE_I32:
|
||||
case TYPE_I64:
|
||||
case TYPE_U8:
|
||||
case TYPE_U16:
|
||||
case TYPE_U32:
|
||||
case TYPE_U64:
|
||||
case TYPE_F32:
|
||||
case TYPE_F64:
|
||||
case ALL_INTS:
|
||||
case ALL_FLOATS:
|
||||
return canonical->builtin.bytesize;
|
||||
case TYPE_IXX:
|
||||
return 8;
|
||||
case TYPE_FXX:
|
||||
return 8;
|
||||
case TYPE_FUNC:
|
||||
case TYPE_POINTER:
|
||||
case TYPE_VARARRAY:
|
||||
@@ -233,7 +222,44 @@ size_t type_size(Type *canonical)
|
||||
case TYPE_ERROR_UNION:
|
||||
TODO
|
||||
}
|
||||
TODO
|
||||
UNREACHABLE
|
||||
}
|
||||
|
||||
size_t type_abi_alignment(Type *canonical)
|
||||
{
|
||||
assert(canonical && canonical->canonical == canonical);
|
||||
switch (canonical->type_kind)
|
||||
{
|
||||
case TYPE_POISONED:
|
||||
case TYPE_TYPEDEF:
|
||||
case TYPE_VOID:
|
||||
UNREACHABLE;
|
||||
case TYPE_META_TYPE:
|
||||
return 0;
|
||||
case TYPE_ENUM:
|
||||
return canonical->decl->enums.type_info->type->canonical->builtin.abi_alignment;
|
||||
case TYPE_ERROR:
|
||||
return type_error->canonical->builtin.abi_alignment;
|
||||
case TYPE_STRUCT:
|
||||
case TYPE_UNION:
|
||||
return canonical->decl->strukt.abi_alignment;
|
||||
case TYPE_BOOL:
|
||||
case ALL_INTS:
|
||||
case ALL_FLOATS:
|
||||
return canonical->builtin.abi_alignment;
|
||||
case TYPE_FUNC:
|
||||
case TYPE_POINTER:
|
||||
case TYPE_VARARRAY:
|
||||
case TYPE_STRING:
|
||||
return t_usz.canonical->builtin.abi_alignment;
|
||||
case TYPE_ARRAY:
|
||||
return type_abi_alignment(canonical->array.base);
|
||||
case TYPE_SUBARRAY:
|
||||
TODO
|
||||
case TYPE_ERROR_UNION:
|
||||
TODO
|
||||
}
|
||||
UNREACHABLE
|
||||
}
|
||||
|
||||
static inline void create_type_cache(Type *canonical_type)
|
||||
@@ -375,7 +401,7 @@ static void type_create(const char *name, Type *location, TypeKind kind, unsigne
|
||||
.type_kind = kind,
|
||||
.builtin.bytesize = (bitsize + 7) / 8,
|
||||
.builtin.bitsize = bitsize,
|
||||
.builtin.min_alignment = align,
|
||||
.builtin.abi_alignment = align,
|
||||
.builtin.pref_alignment = pref_align,
|
||||
.name = name,
|
||||
.canonical = location,
|
||||
@@ -403,7 +429,7 @@ void builtin_setup(Target *target)
|
||||
type_string.type_kind = TYPE_STRING;
|
||||
*/
|
||||
#define DEF_TYPE(_name, _shortname, _type, _bits, _align) \
|
||||
type_create(#_name, &_shortname, _type, _bits, target->align_min_ ## _align, target->align_ ## _align)
|
||||
type_create(#_name, &_shortname, _type, _bits, target->align_ ## _align, target->align_pref_ ## _align)
|
||||
|
||||
DEF_TYPE(bool, t_u1, TYPE_BOOL, 1, byte);
|
||||
DEF_TYPE(float, t_f32, TYPE_F32, 32, float);
|
||||
@@ -424,7 +450,7 @@ type_create(#_name, &_shortname, _type, _bits, target->align_min_ ## _align, tar
|
||||
|
||||
#undef DEF_TYPE
|
||||
|
||||
type_create("void*", &t_voidstar, TYPE_POINTER, target->width_pointer, target->align_min_pointer, target->align_pointer);
|
||||
type_create("void*", &t_voidstar, TYPE_POINTER, target->width_pointer, target->align_pref_pointer, target->align_pointer);
|
||||
create_type_cache(type_void);
|
||||
type_void->type_cache[0] = &t_voidstar;
|
||||
t_voidstar.pointer = type_void;
|
||||
|
||||
@@ -42,6 +42,7 @@ TargetInfo target_info_new()
|
||||
.asm_supported = false,
|
||||
.float_128 = false,
|
||||
.float_16 = false,
|
||||
.align_pointer = 8,
|
||||
.align_byte = 8,
|
||||
.align_c_int = 32,
|
||||
.align_c_long = 32,
|
||||
|
||||
@@ -267,6 +267,7 @@ static inline void* _expand(void *vec, size_t element_size)
|
||||
#define VECEACH(_vec, _index) \
|
||||
for (unsigned _index = 0, __vecsize = vec_size(_vec); _index < __vecsize; _index++)
|
||||
|
||||
|
||||
#define VECNEW(_type, _capacity) ((_type *)(_vec_new(sizeof(_type), _capacity) + 1))
|
||||
#define VECADD(_vec, _value) \
|
||||
({ \
|
||||
|
||||
Reference in New Issue
Block a user