mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Order of function resolution is different. Function prototypes resolved first. Same with LLVM gen. Designated initializer and anonymous fields fixed mostly.
This commit is contained in:
committed by
Christoffer Lerno
parent
9bf89574f9
commit
1d73338fb0
@@ -38,10 +38,15 @@ Things missing:
|
||||
- Bitstruct
|
||||
- Enumset
|
||||
- Typeid
|
||||
- Ranges
|
||||
|
||||
* Arrays
|
||||
- Allow fixed arrays with no larger size than 32 bit unsigned.
|
||||
|
||||
* Struct / union
|
||||
- Cast to union?
|
||||
- Structural typed anonymous structs and casts to them.
|
||||
- Auto deref on access.
|
||||
|
||||
* Expressions
|
||||
- Disallow x >= 0 and x < 0 on unsigned types unless in a macro.
|
||||
@@ -69,4 +74,5 @@ Things missing:
|
||||
- Values: min, max, array
|
||||
- Functions: fomOrdinal, ordinal, fromName, name, fromFullName, fullName, fromQualifiedName, qualifiedName, <value>(), fromValue()
|
||||
|
||||
|
||||
* Error reporting
|
||||
- When a variable fails to parse correctly, store it to prevent follow up errors.
|
||||
|
||||
@@ -117,41 +117,6 @@ union SimpleUnion
|
||||
double f;
|
||||
}
|
||||
|
||||
struct AnonStruct
|
||||
{
|
||||
int a;
|
||||
struct sune
|
||||
{
|
||||
int b;
|
||||
int c;
|
||||
}
|
||||
struct
|
||||
{
|
||||
int b1;
|
||||
int c1;
|
||||
}
|
||||
union
|
||||
{
|
||||
int b2;
|
||||
int c2;
|
||||
}
|
||||
int x;
|
||||
}
|
||||
|
||||
|
||||
func void testAnonStruct()
|
||||
{
|
||||
|
||||
AnonStruct s = { b2 = 3, b1 = 7, sune.b = 1 };
|
||||
AnonStruct foo;
|
||||
|
||||
s.sune.b = 1;
|
||||
s.b1 = 2;
|
||||
s.b2 = 3;
|
||||
s.c2 = 4;
|
||||
|
||||
}
|
||||
|
||||
func void testUnion()
|
||||
{
|
||||
SimpleUnion s;
|
||||
@@ -160,7 +125,7 @@ func void testUnion()
|
||||
s = { 1 };
|
||||
int x = 2;
|
||||
s = { (x = 2) };
|
||||
//s = { f = 1.0 };
|
||||
s = { f = 1.0 };
|
||||
TestUnion tu = { e = TestStruct2 { c = 1 } };
|
||||
tu.e = TestStruct2 { c = 1 };
|
||||
}
|
||||
@@ -290,6 +255,69 @@ func int barok() throws Error, OtherError
|
||||
return 100;
|
||||
}
|
||||
|
||||
struct SimpleStruct
|
||||
{
|
||||
int a;
|
||||
int b;
|
||||
double c;
|
||||
double d;
|
||||
char z1;
|
||||
char z2;
|
||||
}
|
||||
func void testSimpleStruct(int x)
|
||||
{
|
||||
SimpleStruct snoinit;
|
||||
SimpleStruct sinit = { b = 1, d = 3.0, z1 = 1 };
|
||||
sinit.a = 1;
|
||||
sinit.b = 2;
|
||||
printf("a = %d, b = %d (1), c = %f, d = %f (3.0), z1 = %d (1), z2 = %d\n", sinit.a, sinit.b, sinit.c, sinit.d, cast(sinit.z1, int), cast(sinit.z2, int));
|
||||
snoinit.b = 1;
|
||||
snoinit.a = 100;
|
||||
snoinit.d = 3.0;
|
||||
snoinit.c = 2.0;
|
||||
snoinit.z1 = 1;
|
||||
snoinit.z2 = 2;
|
||||
printf("b = %d (1), d = %f (3.0), z1 = %d (1)\n", snoinit.b, snoinit.d, snoinit.z1);
|
||||
}
|
||||
|
||||
struct AnonStruct
|
||||
{
|
||||
int a;
|
||||
struct sune
|
||||
{
|
||||
int b;
|
||||
int c;
|
||||
}
|
||||
struct
|
||||
{
|
||||
int b1;
|
||||
int c1;
|
||||
}
|
||||
union
|
||||
{
|
||||
int b2;
|
||||
int c2;
|
||||
}
|
||||
int x;
|
||||
}
|
||||
|
||||
func void testAnonStruct()
|
||||
{
|
||||
AnonStruct s = { b2 = 3, b1 = 7, sune.b = 1 };
|
||||
AnonStruct foo;
|
||||
|
||||
printf("a = %d, b = %d (1), c = %d, b1 = %d (7), c1 = %d, b2 = %d (3), c2 = %d (3), x = %d\n", s.a, s.sune.b, s.sune.c, s.b1, s.c1, s.b2, s.c2, s.x);
|
||||
|
||||
s.sune.b = 100;
|
||||
s.sune.c = 99;
|
||||
s.b1 = 3;
|
||||
s.b2 = 5;
|
||||
s.c2 = 7;
|
||||
|
||||
printf("a = %d, b = %d (100), c = %d (99), b1 = %d (3), c1 = %d, b2 = %d (7), c2 = %d (7), x = %d\n", s.a, s.sune.b, s.sune.c, s.b1, s.c1, s.b2, s.c2, s.x);
|
||||
|
||||
|
||||
}
|
||||
func int boba(int y, int j)
|
||||
{
|
||||
// hello();
|
||||
@@ -526,6 +554,34 @@ func int testReturnDefer()
|
||||
return i;
|
||||
}
|
||||
|
||||
struct WithArray
|
||||
{
|
||||
int[4] x;
|
||||
}
|
||||
|
||||
func void testArray()
|
||||
{
|
||||
//int[4] zebra = { [0] = 1 };
|
||||
WithArray boo;
|
||||
boo.x[0] = 2;
|
||||
printf("boo.x[0] = %d\n", boo.x[0]);
|
||||
printf("boo.x[2] = %d\n", boo.x[2]);
|
||||
int[4] x;
|
||||
x[1] = 1;
|
||||
x[0] = 3;
|
||||
int y = x[1];
|
||||
int z = 1;
|
||||
int* b = &z;
|
||||
printf("b: %d\n", *b);
|
||||
*b = 3;
|
||||
printf("b: %d\n", *b);
|
||||
printf("z: %d\n", z);
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
printf("x[%d] = %d\n", i, x[i]);
|
||||
}
|
||||
}
|
||||
func void testDefer()
|
||||
{
|
||||
printf("1 == %d\n", testReturnDefer());
|
||||
@@ -557,12 +613,17 @@ JUMP:
|
||||
defer printf("7");
|
||||
printf("6");
|
||||
}
|
||||
|
||||
|
||||
func int main(int x)
|
||||
{
|
||||
printf("Helo!\n");
|
||||
testDefault(y = 99);
|
||||
testPointers(2, 3);
|
||||
testDefer();
|
||||
testArray();
|
||||
testAnonStruct();
|
||||
testSimpleStruct(0);
|
||||
int efd = 9;
|
||||
uint fefoek = 1;
|
||||
printf("Helo: %d\n", efd + cast(fefoek, int));
|
||||
@@ -723,4 +784,5 @@ func void test2(int* x, int y, int z)
|
||||
x + 1;
|
||||
int j1 = x[0];
|
||||
j1 = *x;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1896,7 +1896,14 @@ const char *bigint_to_error_string(const BigInt *bigint, uint64_t base)
|
||||
if (bigint->digit_count == 1 && base == 10)
|
||||
{
|
||||
char *res = NULL;
|
||||
asprintf(&res, "%" PRIu64, bigint->digit);
|
||||
if (bigint->is_negative)
|
||||
{
|
||||
asprintf(&res, "-%" PRIu64, bigint->digit);
|
||||
}
|
||||
else
|
||||
{
|
||||
asprintf(&res, "%" PRIu64, bigint->digit);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
size_t len = bigint->digit_count * 64;
|
||||
|
||||
@@ -133,6 +133,23 @@ typedef struct _Path
|
||||
uint32_t len;
|
||||
} Path;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DESIGNATED_IDENT,
|
||||
DESIGNATED_SUBSCRIPT
|
||||
} DesignatedPathKind;
|
||||
|
||||
typedef struct _DesignatedPath
|
||||
{
|
||||
DesignatedPathKind kind;
|
||||
struct _DesignatedPath *sub_path;
|
||||
Type *type;
|
||||
union
|
||||
{
|
||||
unsigned index;
|
||||
Expr *index_expr;
|
||||
};
|
||||
} DesignatedPath;
|
||||
typedef struct
|
||||
{
|
||||
unsigned char bitsize;
|
||||
@@ -508,6 +525,12 @@ typedef struct
|
||||
Ast **stmts;
|
||||
} ExprFuncBlock;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Expr *left;
|
||||
Expr *right;
|
||||
} ExprRange;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
INITIALIZER_UNKNOWN,
|
||||
@@ -522,6 +545,11 @@ typedef struct
|
||||
Expr** initializer_expr;
|
||||
} ExprInitializer;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
DesignatedPath *path;
|
||||
Expr* value;
|
||||
} ExprDesignatedInit;
|
||||
|
||||
struct _Expr
|
||||
{
|
||||
@@ -530,9 +558,11 @@ struct _Expr
|
||||
SourceRange span;
|
||||
Type *type;
|
||||
union {
|
||||
ExprDesignatedInit designated_init_expr;
|
||||
Expr *group_expr;
|
||||
ExprCast cast_expr;
|
||||
ExprConst const_expr;
|
||||
ExprRange range_expr;
|
||||
ExprStructValue struct_value_expr;
|
||||
ExprTypeRef type_access;
|
||||
ExprTry try_expr;
|
||||
@@ -1151,6 +1181,7 @@ static inline Token wrap(const char *string)
|
||||
|
||||
Type *type_get_ptr(Type *ptr_type);
|
||||
Type *type_get_meta(Type *meta_type);
|
||||
Type *type_get_indexed_type(Type *type);
|
||||
Type *type_get_array(Type *arr_type, uint64_t len);
|
||||
Type *type_signed_int_by_bitsize(unsigned bytesize);
|
||||
Type *type_unsigned_int_by_bitsize(unsigned bytesize);
|
||||
|
||||
@@ -230,6 +230,8 @@ typedef enum
|
||||
EXPR_SCOPED_EXPR,
|
||||
EXPR_MACRO_EXPR,
|
||||
EXPR_EXPR_BLOCK,
|
||||
EXPR_RANGE,
|
||||
EXPR_DESIGNATED_INITIALIZER,
|
||||
} ExprKind;
|
||||
|
||||
|
||||
|
||||
@@ -200,6 +200,11 @@ void llvm_codegen(Context *context)
|
||||
{
|
||||
gencontext_emit_function_decl(&gen_context, context->functions[i]);
|
||||
}
|
||||
VECEACH(context->functions, i)
|
||||
{
|
||||
Decl *decl = context->functions[i];
|
||||
if (decl->func.body) gencontext_emit_function_body(&gen_context, decl);
|
||||
}
|
||||
|
||||
|
||||
gencontext_print_llvm_ir(&gen_context);
|
||||
|
||||
@@ -82,6 +82,18 @@ static inline LLVMValueRef gencontext_emit_subscript_addr_from_value(GenContext
|
||||
llvm_type(parent_type->pointer),
|
||||
parent, &index, 1, "[]");
|
||||
case TYPE_ARRAY:
|
||||
// TODO insert trap on overflow.
|
||||
{
|
||||
LLVMValueRef zero = LLVMConstInt(LLVMIntType(32), 0, false);
|
||||
LLVMValueRef indices[2] = {
|
||||
zero,
|
||||
index,
|
||||
};
|
||||
return LLVMBuildInBoundsGEP2(context->builder,
|
||||
llvm_type(parent_type),
|
||||
parent, indices, 2, "[x]");
|
||||
|
||||
}
|
||||
case TYPE_VARARRAY:
|
||||
case TYPE_SUBARRAY:
|
||||
case TYPE_STRING:
|
||||
@@ -93,14 +105,45 @@ static inline LLVMValueRef gencontext_emit_subscript_addr_from_value(GenContext
|
||||
}
|
||||
static inline LLVMValueRef gencontext_emit_subscript_addr(GenContext *context, Expr *expr)
|
||||
{
|
||||
LLVMValueRef parent = gencontext_emit_expr(context, expr->subscript_expr.expr);
|
||||
return gencontext_emit_subscript_addr_from_value(context, parent, expr->subscript_expr.expr->type->canonical, expr->subscript_expr.index);
|
||||
Expr *parent = expr->subscript_expr.expr;
|
||||
Expr *index = expr->subscript_expr.index;
|
||||
LLVMValueRef index_value = gencontext_emit_expr(context, index);
|
||||
LLVMValueRef parent_value;
|
||||
switch (parent->type->canonical->type_kind)
|
||||
{
|
||||
case TYPE_POINTER:
|
||||
parent_value = gencontext_emit_expr(context, expr->subscript_expr.expr);
|
||||
return LLVMBuildGEP2(context->builder,
|
||||
llvm_type(parent->type->canonical),
|
||||
parent_value, &index_value, 1, "[]");
|
||||
case TYPE_ARRAY:
|
||||
{
|
||||
// TODO insert trap on overflow.
|
||||
LLVMValueRef zero = LLVMConstInt(LLVMIntType(32), 0, false);
|
||||
LLVMValueRef indices[2] = {
|
||||
zero,
|
||||
index_value,
|
||||
};
|
||||
parent_value = gencontext_emit_address(context, expr->subscript_expr.expr);
|
||||
return LLVMBuildInBoundsGEP2(context->builder,
|
||||
llvm_type(parent->type),
|
||||
parent_value, indices, 2, "[x]");
|
||||
}
|
||||
case TYPE_VARARRAY:
|
||||
case TYPE_SUBARRAY:
|
||||
case TYPE_STRING:
|
||||
TODO
|
||||
default:
|
||||
UNREACHABLE
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static LLVMValueRef gencontext_emit_member_addr(GenContext *context, LLVMValueRef value, Decl *parent, Decl *member)
|
||||
{
|
||||
unsigned index;
|
||||
Decl *current_parent;
|
||||
assert(member->resolve_status == RESOLVE_DONE);
|
||||
if (decl_is_struct_type(member))
|
||||
{
|
||||
index = member->strukt.id;
|
||||
@@ -119,9 +162,9 @@ static LLVMValueRef gencontext_emit_member_addr(GenContext *context, LLVMValueRe
|
||||
|
||||
if (current_parent->decl_kind == DECL_UNION)
|
||||
{
|
||||
return LLVMBuildBitCast(context->builder, value, LLVMPointerType(llvm_type(member->type), 0), "unionref");
|
||||
return LLVMBuildBitCast(context->builder, value, LLVMPointerType(llvm_type(member->type), 0), member->name ?: "anon");
|
||||
}
|
||||
return LLVMBuildStructGEP2(context->builder, llvm_type(current_parent->type), value, index, "structref");
|
||||
return LLVMBuildStructGEP2(context->builder, llvm_type(current_parent->type), value, index, member->name ?: "anon");
|
||||
}
|
||||
|
||||
|
||||
@@ -151,8 +194,13 @@ LLVMValueRef gencontext_emit_address(GenContext *context, Expr *expr)
|
||||
{
|
||||
switch (expr->expr_kind)
|
||||
{
|
||||
case EXPR_RANGE:
|
||||
TODO
|
||||
case EXPR_EXPR_BLOCK:
|
||||
TODO
|
||||
case EXPR_DESIGNATED_INITIALIZER:
|
||||
// Should only appear when generating designated initializers.
|
||||
UNREACHABLE
|
||||
case EXPR_IDENTIFIER:
|
||||
return expr->identifier_expr.decl->var.backend_ref;
|
||||
case EXPR_UNARY:
|
||||
@@ -252,28 +300,7 @@ static inline LLVMValueRef gencontext_emit_cast_expr(GenContext *context, Expr *
|
||||
}
|
||||
|
||||
|
||||
static inline LLVMValueRef gencontext_emit_designated_initializer(GenContext *context, Type *parent_type, LLVMValueRef parent, Expr *expr)
|
||||
{
|
||||
assert(parent_type == parent_type->canonical);
|
||||
switch (expr->expr_kind)
|
||||
{
|
||||
case EXPR_SUBSCRIPT:
|
||||
if (expr->subscript_expr.expr)
|
||||
{
|
||||
parent = gencontext_emit_designated_initializer(context, parent_type, parent, expr->subscript_expr.expr);
|
||||
parent_type = expr->subscript_expr.expr->type->canonical;
|
||||
}
|
||||
return gencontext_emit_subscript_addr_from_value(context, parent, parent_type, expr->subscript_expr.index);
|
||||
case EXPR_ACCESS:
|
||||
parent = gencontext_emit_designated_initializer(context, parent_type, parent, expr->access_expr.parent);
|
||||
parent_type = expr->subscript_expr.expr->type->canonical;
|
||||
return gencontext_emit_member_addr(context, parent, parent_type->decl, expr->access_expr.ref);
|
||||
case EXPR_IDENTIFIER:
|
||||
return gencontext_emit_member_addr(context, parent, parent_type->decl, expr->identifier_expr.decl);
|
||||
default:
|
||||
UNREACHABLE
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Emit a Foo { .... } literal.
|
||||
@@ -293,7 +320,7 @@ static inline LLVMValueRef gencontext_emit_initializer_list_expr(GenContext *con
|
||||
LLVMConstInt(llvm_type(type_byte), 0, false),
|
||||
LLVMConstInt(llvm_type(type_ulong), expr->type->decl->strukt.size, false),
|
||||
expr->type->decl->strukt.abi_alignment);
|
||||
return ref;
|
||||
return LLVMBuildLoad2(context->builder, type, ref, "");
|
||||
}
|
||||
|
||||
Expr **elements = expr->expr_initializer.initializer_expr;
|
||||
@@ -307,7 +334,7 @@ static inline LLVMValueRef gencontext_emit_initializer_list_expr(GenContext *con
|
||||
LLVMValueRef init_value = gencontext_emit_expr(context, elements[0]);
|
||||
LLVMValueRef u = LLVMBuildBitCast(context->builder, ref, LLVMPointerType(llvm_type(elements[0]->type->canonical), 0), "");
|
||||
LLVMBuildStore(context->builder, init_value, u);
|
||||
return ref;
|
||||
return LLVMBuildLoad2(context->builder, type, ref, "");
|
||||
}
|
||||
VECEACH(elements, i)
|
||||
{
|
||||
@@ -316,7 +343,7 @@ static inline LLVMValueRef gencontext_emit_initializer_list_expr(GenContext *con
|
||||
LLVMValueRef subref = LLVMBuildStructGEP2(context->builder, type, ref, i, "");
|
||||
LLVMBuildStore(context->builder, init_value, subref);
|
||||
}
|
||||
return ref;
|
||||
return LLVMBuildLoad2(context->builder, type, ref, "");
|
||||
}
|
||||
|
||||
|
||||
@@ -328,11 +355,48 @@ static inline LLVMValueRef gencontext_emit_initializer_list_expr(GenContext *con
|
||||
VECEACH(elements, i)
|
||||
{
|
||||
Expr *element = elements[i];
|
||||
LLVMValueRef sub_value = gencontext_emit_expr(context, element->binary_expr.right);
|
||||
LLVMValueRef sub_ref = gencontext_emit_designated_initializer(context, expr->type->canonical, ref, element->binary_expr.left);
|
||||
DesignatedPath *path = element->designated_init_expr.path;
|
||||
LLVMValueRef sub_value = gencontext_emit_expr(context, element->designated_init_expr.value);
|
||||
LLVMValueRef sub_ref = ref;
|
||||
Type *parent_type = expr->type->canonical;
|
||||
while (path)
|
||||
{
|
||||
switch (path->kind)
|
||||
{
|
||||
case DESIGNATED_IDENT:
|
||||
if (parent_type->canonical->type_kind == TYPE_UNION)
|
||||
{
|
||||
sub_ref = LLVMBuildBitCast(context->builder, sub_ref, LLVMPointerType(llvm_type(path->type), 0), "unionref");
|
||||
}
|
||||
else
|
||||
{
|
||||
sub_ref = LLVMBuildStructGEP2(context->builder, llvm_type(parent_type), sub_ref, path->index, "structref");
|
||||
}
|
||||
break;
|
||||
case DESIGNATED_SUBSCRIPT:
|
||||
{
|
||||
// TODO range, more arrays
|
||||
LLVMValueRef zero = LLVMConstInt(LLVMIntType(32), 0, false);
|
||||
LLVMValueRef index = gencontext_emit_expr(context, path->index_expr);
|
||||
LLVMValueRef indices[2] = {
|
||||
zero,
|
||||
index,
|
||||
};
|
||||
sub_ref = LLVMBuildInBoundsGEP2(context->builder,
|
||||
llvm_type(parent_type),
|
||||
sub_ref, indices, 2, "[x]");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
UNREACHABLE;
|
||||
|
||||
}
|
||||
parent_type = path->type;
|
||||
path = path->sub_path;
|
||||
}
|
||||
LLVMBuildStore(context->builder, sub_value, sub_ref);
|
||||
}
|
||||
return ref;
|
||||
return LLVMBuildLoad2(context->builder, type, ref, "");
|
||||
}
|
||||
|
||||
static inline LLVMValueRef gencontext_emit_inc_dec_change(GenContext *context, bool use_mod, LLVMValueRef current_value, Expr *expr, int diff)
|
||||
@@ -902,14 +966,6 @@ LLVMValueRef gencontext_emit_call_expr(GenContext *context, Expr *expr)
|
||||
|
||||
|
||||
|
||||
static inline LLVMValueRef gencontext_emit_access_expr(GenContext *context, Expr *expr)
|
||||
{
|
||||
// Improve, add string description to the access?
|
||||
LLVMValueRef value = gencontext_emit_address(context, expr->access_expr.parent);
|
||||
LLVMValueRef val = LLVMBuildStructGEP2(context->builder, llvm_type(expr->access_expr.parent->type), value, expr->access_expr.ref->var.id, "");
|
||||
return LLVMBuildLoad2(context->builder, gencontext_get_llvm_type(context, expr->type), val, "");
|
||||
}
|
||||
|
||||
static inline LLVMValueRef gencontext_emit_expression_list_expr(GenContext *context, Expr *expr)
|
||||
{
|
||||
LLVMValueRef value = NULL;
|
||||
@@ -965,8 +1021,13 @@ LLVMValueRef gencontext_emit_expr(GenContext *context, Expr *expr)
|
||||
{
|
||||
switch (expr->expr_kind)
|
||||
{
|
||||
case EXPR_RANGE:
|
||||
TODO
|
||||
case EXPR_POISONED:
|
||||
UNREACHABLE
|
||||
case EXPR_DESIGNATED_INITIALIZER:
|
||||
// Should only appear when generating designated initializers.
|
||||
UNREACHABLE
|
||||
case EXPR_EXPR_BLOCK:
|
||||
return gencontext_emit_expr_block(context, expr);
|
||||
case EXPR_SCOPED_EXPR:
|
||||
@@ -990,13 +1051,12 @@ LLVMValueRef gencontext_emit_expr(GenContext *context, Expr *expr)
|
||||
UNREACHABLE
|
||||
case EXPR_IDENTIFIER:
|
||||
case EXPR_SUBSCRIPT:
|
||||
case EXPR_ACCESS:
|
||||
return gencontext_load_expr(context, gencontext_emit_address(context, expr));
|
||||
case EXPR_CALL:
|
||||
return gencontext_emit_call_expr(context, expr);
|
||||
case EXPR_GROUP:
|
||||
return gencontext_emit_expr(context, expr->group_expr);
|
||||
case EXPR_ACCESS:
|
||||
return gencontext_emit_access_expr(context, expr);
|
||||
case EXPR_INITIALIZER_LIST:
|
||||
return gencontext_emit_initializer_list_expr(context, expr);
|
||||
case EXPR_EXPRESSION_LIST:
|
||||
|
||||
@@ -223,7 +223,6 @@ void gencontext_emit_function_decl(GenContext *context, Decl *decl)
|
||||
0);
|
||||
LLVMSetSubprogram(decl->func.backend_value, context->debug.function);
|
||||
}
|
||||
if (decl->func.body) gencontext_emit_function_body(context, decl);
|
||||
}
|
||||
|
||||
void gencontext_emit_extern_decl(GenContext *context, Decl *decl)
|
||||
|
||||
@@ -98,7 +98,7 @@ static inline LLVMBasicBlockRef gencontext_create_free_block(GenContext *context
|
||||
{
|
||||
return LLVMCreateBasicBlockInContext(context->context, name);
|
||||
}
|
||||
|
||||
void gencontext_emit_function_body(GenContext *context, Decl *decl);
|
||||
void gencontext_emit_implicit_return(GenContext *context);
|
||||
void gencontext_emit_function_decl(GenContext *context, Decl *decl);
|
||||
void gencontext_emit_extern_decl(GenContext *context, Decl *decl);
|
||||
|
||||
@@ -110,14 +110,13 @@ static inline LLVMTypeRef llvm_type_from_ptr(LLVMContextRef context, Type *type)
|
||||
|
||||
static inline LLVMTypeRef llvm_type_from_array(LLVMContextRef context, Type *type)
|
||||
{
|
||||
LLVMTypeRef base_llvm_type = llvm_get_type(context, type->array.base);
|
||||
|
||||
if (type->canonical != type)
|
||||
{
|
||||
return type->backend_type = llvm_get_type(context, type->canonical);
|
||||
}
|
||||
|
||||
return type->backend_type = LLVMPointerType(base_llvm_type, /** TODO **/0);
|
||||
LLVMTypeRef base_llvm_type = llvm_get_type(context, type->array.base);
|
||||
return type->backend_type = LLVMArrayType(base_llvm_type, type->array.len);
|
||||
}
|
||||
|
||||
LLVMTypeRef llvm_func_type(LLVMContextRef context, Type *type)
|
||||
@@ -206,7 +205,7 @@ LLVMTypeRef llvm_get_type(LLVMContextRef context, Type *type)
|
||||
return type->backend_type = llvm_type_from_ptr(context, type);
|
||||
case TYPE_STRING:
|
||||
// TODO
|
||||
return type->backend_type = LLVMPointerType(LLVMTYPE(type_char), 0);
|
||||
return type->backend_type = LLVMPointerType(llvm_get_type(context, type_char), 0);
|
||||
case TYPE_ARRAY:
|
||||
return type->backend_type = llvm_type_from_array(context, type);
|
||||
case TYPE_SUBARRAY:
|
||||
|
||||
@@ -75,7 +75,17 @@ bool parse_param_list(Context *context, Expr ***result, bool allow_type)
|
||||
TypeInfo *type = NULL;
|
||||
Expr *expr = NULL;
|
||||
SourceRange start = context->tok.span;
|
||||
if (!parse_type_or_expr(context, &expr, &type)) return false;
|
||||
// Special handling of [123]
|
||||
if (try_consume(context, TOKEN_LBRACKET))
|
||||
{
|
||||
expr = TRY_EXPR_OR(parse_expr(context), false);
|
||||
CONSUME_OR(TOKEN_RBRACKET, false);
|
||||
expr = TRY_EXPR_OR(parse_precedence_with_left_side(context, expr, PREC_ASSIGNMENT), false);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!parse_type_or_expr(context, &expr, &type)) return false;
|
||||
}
|
||||
if (!expr)
|
||||
{
|
||||
if (!allow_type)
|
||||
@@ -253,8 +263,11 @@ 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->expr_initializer.initializer_expr, false)) return &poisoned_expr;
|
||||
CONSUME_OR(TOKEN_RBRACE, &poisoned_expr);
|
||||
if (!try_consume(context, TOKEN_RBRACE))
|
||||
{
|
||||
if (!parse_param_list(context, &initializer_list->expr_initializer.initializer_expr, false)) return &poisoned_expr;
|
||||
CONSUME_OR(TOKEN_RBRACE, &poisoned_expr);
|
||||
}
|
||||
return initializer_list;
|
||||
}
|
||||
|
||||
@@ -315,6 +328,7 @@ static Expr *parse_subscript_expr(Context *context, Expr *left)
|
||||
Expr *subscript_ast = EXPR_NEW_EXPR(EXPR_SUBSCRIPT, left);
|
||||
subscript_ast->subscript_expr.expr = left;
|
||||
subscript_ast->subscript_expr.index = index;
|
||||
RANGE_EXTEND_PREV(subscript_ast);
|
||||
return subscript_ast;
|
||||
}
|
||||
|
||||
|
||||
@@ -119,6 +119,7 @@ static inline bool sema_analyse_struct_member(Context *context, Decl *decl)
|
||||
sema_set_struct_size(decl);
|
||||
}
|
||||
DEBUG_LOG("Analysis complete.");
|
||||
decl->resolve_status = RESOLVE_DONE;
|
||||
return decl_ok(decl);
|
||||
}
|
||||
assert(decl->decl_kind == DECL_VAR);
|
||||
@@ -429,7 +430,6 @@ static inline bool sema_analyse_func(Context *context, Decl *decl)
|
||||
{
|
||||
if (!sema_analyse_method_function(context, decl)) return decl_poison(decl);
|
||||
}
|
||||
if (decl->func.body && !sema_analyse_function_body(context, decl)) return decl_poison(decl);
|
||||
if (decl->name == main_name)
|
||||
{
|
||||
if (decl->visibility == VISIBLE_LOCAL)
|
||||
|
||||
@@ -351,11 +351,12 @@ static inline bool sema_expr_analyse_call(Context *context, Type *to, Expr *expr
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool sema_expr_analyse_subscript_after_parent_resolution(Context *context, Expr *expr)
|
||||
static inline bool sema_expr_analyse_subscript_after_parent_resolution(Context *context, Type *parent, Expr *expr)
|
||||
{
|
||||
assert(expr->expr_kind == EXPR_SUBSCRIPT);
|
||||
assert(expr->subscript_expr.expr->resolve_status == RESOLVE_DONE);
|
||||
Type *type = expr->subscript_expr.expr->type->canonical;
|
||||
Expr *subscripted = expr->subscript_expr.expr;
|
||||
Type *type = parent ? parent->canonical : subscripted->type->canonical;
|
||||
Expr *index = expr->subscript_expr.index;
|
||||
Type *inner_type;
|
||||
switch (type->type_kind)
|
||||
{
|
||||
@@ -372,16 +373,45 @@ static inline bool sema_expr_analyse_subscript_after_parent_resolution(Context *
|
||||
inner_type = type_char;
|
||||
break;
|
||||
default:
|
||||
SEMA_ERROR(expr->subscript_expr.expr, "Cannot index '%s'.", type_to_error_string(type));
|
||||
SEMA_ERROR((parent ? expr : subscripted), "Cannot index '%s'.", type_to_error_string(type));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!sema_analyse_expr(context, type_isize, expr->subscript_expr.index)) return false;
|
||||
if (!sema_analyse_expr(context, type_isize, index)) return false;
|
||||
|
||||
// Unless we already have type_usize, cast to type_isize;
|
||||
if (expr->subscript_expr.index->type->canonical->type_kind != type_usize->canonical->type_kind)
|
||||
if (index->type->canonical->type_kind != type_usize->canonical->type_kind)
|
||||
{
|
||||
if (!cast_implicit(expr->subscript_expr.index, type_isize)) return false;
|
||||
if (!cast_implicit(index, type_isize)) return false;
|
||||
}
|
||||
// Check range
|
||||
if (index->expr_kind == EXPR_CONST)
|
||||
{
|
||||
switch (type->type_kind)
|
||||
{
|
||||
case TYPE_ARRAY:
|
||||
{
|
||||
BigInt size;
|
||||
bigint_init_unsigned(&size, type->array.len);
|
||||
if (bigint_cmp(&size, &index->const_expr.i) != CMP_GT)
|
||||
{
|
||||
SEMA_ERROR(index, "Array index out of bounds, was %s, exceeding max index of %llu.",
|
||||
bigint_to_error_string(&index->const_expr.i, 10), type->array.len - 1);
|
||||
return false;
|
||||
}
|
||||
// fallthrough
|
||||
}
|
||||
case TYPE_VARARRAY:
|
||||
case TYPE_SUBARRAY:
|
||||
if (bigint_cmp_zero(&index->const_expr.i) == CMP_LT)
|
||||
{
|
||||
SEMA_ERROR(index, "Array index out of bounds, was %s.", bigint_to_error_string(&index->const_expr.i, 10));
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
expr->type = inner_type;
|
||||
return true;
|
||||
@@ -391,7 +421,7 @@ static inline bool sema_expr_analyse_subscript(Context *context, Type *to, Expr
|
||||
{
|
||||
if (!sema_analyse_expr(context, NULL, expr->subscript_expr.expr)) return false;
|
||||
|
||||
return sema_expr_analyse_subscript_after_parent_resolution(context, expr);
|
||||
return sema_expr_analyse_subscript_after_parent_resolution(context, NULL, expr);
|
||||
}
|
||||
|
||||
static inline bool sema_expr_analyse_method_function(Context *context, Expr *expr, Decl *decl, bool is_pointer)
|
||||
@@ -436,9 +466,10 @@ static inline bool sema_expr_analyse_group(Context *context, Type *to, Expr *exp
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static inline bool sema_expr_analyse_access_after_parent_resolution(Context *context, Expr *expr)
|
||||
static inline bool sema_expr_analyse_access(Context *context, Expr *expr)
|
||||
{
|
||||
if (!sema_analyse_expr(context, NULL, expr->access_expr.parent)) return false;
|
||||
|
||||
assert(expr->expr_kind == EXPR_ACCESS);
|
||||
assert(expr->access_expr.parent->resolve_status == RESOLVE_DONE);
|
||||
|
||||
@@ -486,12 +517,6 @@ static inline bool sema_expr_analyse_access_after_parent_resolution(Context *con
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool sema_expr_analyse_access(Context *context, Expr *expr)
|
||||
{
|
||||
if (!sema_analyse_expr(context, NULL, expr->access_expr.parent)) return false;
|
||||
return sema_expr_analyse_access_after_parent_resolution(context, expr);
|
||||
}
|
||||
|
||||
|
||||
static inline bool sema_expr_analyse_type_access(Context *context, Type *to, Expr *expr)
|
||||
{
|
||||
@@ -550,78 +575,172 @@ static inline bool sema_expr_analyse_type_access(Context *context, Type *to, Exp
|
||||
return false;
|
||||
}
|
||||
|
||||
static Decl *sema_analyse_init_path(Context *context, Decl *strukt, Expr *expr);
|
||||
static DesignatedPath *sema_analyse_init_path(Context *context, DesignatedPath *path, Expr *expr);
|
||||
|
||||
static Decl *sema_analyse_init_identifier_string(Context *context, Decl *strukt, const char *string)
|
||||
static DesignatedPath *sema_analyse_init_identifier_string(Context *context, DesignatedPath *parent_path, const char *string)
|
||||
{
|
||||
assert(decl_is_struct_type(strukt));
|
||||
Decl **members = strukt->strukt.members;
|
||||
assert(type_is_structlike(parent_path->type));
|
||||
Decl **members = parent_path->type->decl->strukt.members;
|
||||
VECEACH(members, i)
|
||||
{
|
||||
Decl *member = members[i];
|
||||
if (member->name == string) return member;
|
||||
if (member->name == string)
|
||||
{
|
||||
DesignatedPath *sub_path = CALLOCS(DesignatedPath);
|
||||
sub_path->type = member->type;
|
||||
sub_path->kind = DESIGNATED_IDENT;
|
||||
sub_path->index = i;
|
||||
parent_path->sub_path = sub_path;
|
||||
return sub_path;
|
||||
}
|
||||
if (!member->name)
|
||||
{
|
||||
Decl *anonymous_member = sema_analyse_init_identifier_string(context, member->type->decl, string);
|
||||
if (anonymous_member) return anonymous_member;
|
||||
DesignatedPath temp_path;
|
||||
temp_path.type = member->type;
|
||||
DesignatedPath *found = sema_analyse_init_identifier_string(context, &temp_path, string);
|
||||
if (!found) continue;
|
||||
DesignatedPath *real_path = malloc_arena(sizeof(DesignatedPath));
|
||||
*real_path = temp_path;
|
||||
real_path->index = i;
|
||||
real_path->kind = DESIGNATED_IDENT;
|
||||
parent_path->sub_path = real_path;
|
||||
return found;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static Decl *sema_analyse_init_identifier(Context *context, Decl *strukt, Expr *expr)
|
||||
|
||||
static DesignatedPath *sema_analyse_init_access(Context *context, DesignatedPath *parent, Expr *access_expr)
|
||||
{
|
||||
assert(expr->resolve_status == RESOLVE_NOT_DONE);
|
||||
expr->resolve_status = RESOLVE_RUNNING;
|
||||
Decl *res = sema_analyse_init_identifier_string(context, strukt, expr->identifier_expr.identifier);
|
||||
if (!res) return NULL;
|
||||
expr->identifier_expr.decl = res;
|
||||
expr->resolve_status = RESOLVE_DONE;
|
||||
expr->type = res->type;
|
||||
return res;
|
||||
DesignatedPath *last_path = sema_analyse_init_path(context, parent, access_expr->access_expr.parent);
|
||||
if (!last_path) return NULL;
|
||||
return sema_analyse_init_identifier_string(context, last_path, access_expr->access_expr.sub_element.string);
|
||||
}
|
||||
|
||||
static Decl *sema_analyse_init_access(Context *context, Decl *strukt, Expr *access_expr)
|
||||
static bool expr_cast_to_index(Expr *index)
|
||||
{
|
||||
assert(access_expr->resolve_status == RESOLVE_NOT_DONE);
|
||||
access_expr->resolve_status = RESOLVE_RUNNING;
|
||||
Decl *decl = sema_analyse_init_path(context, strukt, access_expr->access_expr.parent);
|
||||
if (!decl || !decl_is_struct_type(decl->type->decl))
|
||||
if (index->expr_kind == EXPR_RANGE)
|
||||
{
|
||||
access_expr->resolve_status = RESOLVE_DONE;
|
||||
return NULL;
|
||||
TODO
|
||||
}
|
||||
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;
|
||||
if (index->type->canonical->type_kind == type_usize->canonical->type_kind) return true;
|
||||
return cast_implicit(index, type_isize);
|
||||
}
|
||||
|
||||
static Decl *sema_analyse_init_subscript(Context *context, Decl *array, Expr *subscript)
|
||||
static bool expr_check_index_in_range(Type *type, Expr *index)
|
||||
{
|
||||
TODO
|
||||
if (array->type->type_kind != TYPE_ARRAY)
|
||||
if (index->expr_kind == EXPR_RANGE)
|
||||
{
|
||||
|
||||
return expr_check_index_in_range(type, index->range_expr.left) & expr_check_index_in_range(type, index->range_expr.right);
|
||||
}
|
||||
assert(type == type->canonical);
|
||||
if (index->expr_kind == EXPR_CONST)
|
||||
{
|
||||
switch (type->type_kind)
|
||||
{
|
||||
case TYPE_ARRAY:
|
||||
{
|
||||
BigInt size;
|
||||
bigint_init_unsigned(&size, type->array.len);
|
||||
if (bigint_cmp(&size, &index->const_expr.i) != CMP_GT)
|
||||
{
|
||||
SEMA_ERROR(index, "Array index out of bounds, was %s, exceeding max index of %llu.",
|
||||
bigint_to_error_string(&index->const_expr.i, 10), type->array.len - 1);
|
||||
return false;
|
||||
}
|
||||
// fallthrough
|
||||
}
|
||||
case TYPE_VARARRAY:
|
||||
case TYPE_SUBARRAY:
|
||||
if (bigint_cmp_zero(&index->const_expr.i) == CMP_LT)
|
||||
{
|
||||
SEMA_ERROR(index, "Array index out of bounds, was %s.", bigint_to_error_string(&index->const_expr.i, 10));
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case TYPE_STRING:
|
||||
TODO
|
||||
default:
|
||||
UNREACHABLE
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
static DesignatedPath *sema_analyse_init_subscript(Context *context, DesignatedPath *parent, Expr *expr)
|
||||
{
|
||||
assert(expr->expr_kind == EXPR_SUBSCRIPT);
|
||||
DesignatedPath *path = sema_analyse_init_path(context, parent, expr->subscript_expr.expr);
|
||||
if (!path) return NULL;
|
||||
|
||||
Type *type = path->type;
|
||||
if (type->canonical->type_kind == TYPE_POINTER)
|
||||
{
|
||||
SEMA_ERROR(expr, "It's not possible to subscript a pointer field in a designated initializer.");
|
||||
return false;
|
||||
}
|
||||
|
||||
Expr *index = expr->subscript_expr.index;
|
||||
Type *inner_type = type_get_indexed_type(type);
|
||||
if (!inner_type)
|
||||
{
|
||||
SEMA_ERROR(expr, "Not possible to index a value of type '%s'.", type_to_error_string(type));
|
||||
return false;
|
||||
}
|
||||
if (!sema_analyse_expr(context, type_isize, index)) return false;
|
||||
|
||||
// Unless we already have type_usize, cast to type_isize;
|
||||
if (!expr_cast_to_index(index)) return false;
|
||||
|
||||
// Check range
|
||||
if (!expr_check_index_in_range(type->canonical, index)) return false;
|
||||
|
||||
DesignatedPath *sub_path = CALLOCS(DesignatedPath);
|
||||
path->sub_path = sub_path;
|
||||
sub_path->type = inner_type;
|
||||
sub_path->kind = DESIGNATED_SUBSCRIPT;
|
||||
sub_path->index_expr = index;
|
||||
return sub_path;
|
||||
}
|
||||
|
||||
static Decl *sema_analyse_init_path(Context *context, Decl *strukt, Expr *expr)
|
||||
static DesignatedPath *sema_analyse_init_path(Context *context, DesignatedPath *parent, Expr *expr)
|
||||
{
|
||||
switch (expr->expr_kind)
|
||||
{
|
||||
case EXPR_ACCESS:
|
||||
return sema_analyse_init_access(context, strukt, expr);
|
||||
return sema_analyse_init_access(context, parent, expr);
|
||||
case EXPR_IDENTIFIER:
|
||||
return sema_analyse_init_identifier(context, strukt, expr);
|
||||
return sema_analyse_init_identifier_string(context, parent, expr->identifier_expr.identifier);
|
||||
case EXPR_SUBSCRIPT:
|
||||
return sema_analyse_init_subscript(context, strukt, expr);
|
||||
return sema_analyse_init_subscript(context, parent, expr);
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static bool sema_expr_analyse_struct_designated_initializer(Context *context, Decl *assigned, Expr *initializer)
|
||||
/**
|
||||
* Recursively find a node in a declaration.
|
||||
* @return NULL if it wasn't found, otherwise the member.
|
||||
*/
|
||||
DesignatedInitializer *find_initializer(Decl *decl, DesignatedInitializer *initializer, const char* name)
|
||||
{
|
||||
Decl** compare_members = decl->strukt.members;
|
||||
VECEACH(compare_members, i)
|
||||
{
|
||||
Decl *member = compare_members[i];
|
||||
if (!member->name)
|
||||
{
|
||||
DesignatedInitializer *sub_initializer = initializer->initializers[i];
|
||||
DesignatedInitializer *found = find_initializer(member, sub_initializer, name);
|
||||
if (found) return found;
|
||||
}
|
||||
else if (member->name == name) return initializer;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static bool sema_expr_analyse_struct_designated_initializer(Context *context, Type *assigned, Expr *initializer)
|
||||
{
|
||||
Expr **init_expressions = initializer->expr_initializer.initializer_expr;
|
||||
|
||||
@@ -635,15 +754,20 @@ static bool sema_expr_analyse_struct_designated_initializer(Context *context, De
|
||||
SEMA_ERROR(expr, "Expected an initializer on the format 'foo = 123' here.");
|
||||
return false;
|
||||
}
|
||||
Expr *path = expr->binary_expr.left;
|
||||
if (!sema_analyse_init_path(context, assigned, path))
|
||||
Expr *init_expr = expr->binary_expr.left;
|
||||
DesignatedPath path = { .type = assigned };
|
||||
DesignatedPath *last_path = sema_analyse_init_path(context, &path, init_expr);
|
||||
if (!last_path)
|
||||
{
|
||||
SEMA_ERROR(path, "This is not a valid member of '%s'.", type_to_error_string(assigned->type));
|
||||
SEMA_ERROR(expr, "This is not a valid member of '%s'.", type_to_error_string(assigned));
|
||||
return false;
|
||||
}
|
||||
Expr *value = expr->binary_expr.right;
|
||||
if (!sema_analyse_expr_of_required_type(context, path->type, value)) return false;
|
||||
expr->type = path->type;
|
||||
if (!sema_analyse_expr_of_required_type(context, last_path->type, value)) return false;
|
||||
expr->expr_kind = EXPR_DESIGNATED_INITIALIZER;
|
||||
expr->designated_init_expr.path = path.sub_path;
|
||||
expr->designated_init_expr.value = value;
|
||||
expr->resolve_status = RESOLVE_DONE;
|
||||
}
|
||||
initializer->expr_initializer.init_type = INITIALIZER_DESIGNATED;
|
||||
return true;
|
||||
@@ -702,7 +826,7 @@ static inline bool sema_expr_analyse_struct_initializer(Context *context, Type *
|
||||
// this means that in this case we're actually not resolving macros here.
|
||||
if (init_expressions[0]->expr_kind == EXPR_BINARY && init_expressions[0]->binary_expr.operator == BINARYOP_ASSIGN)
|
||||
{
|
||||
return sema_expr_analyse_struct_designated_initializer(context, assigned->decl, expr);
|
||||
return sema_expr_analyse_struct_designated_initializer(context, assigned, expr);
|
||||
}
|
||||
|
||||
// 3. Otherwise use the plain initializer.
|
||||
@@ -718,10 +842,7 @@ static inline bool sema_expr_analyse_initializer_list(Context *context, Type *to
|
||||
{
|
||||
case TYPE_STRUCT:
|
||||
case TYPE_UNION:
|
||||
if (decl_is_struct_type(assigned->decl)) return sema_expr_analyse_struct_initializer(context,
|
||||
assigned,
|
||||
expr);
|
||||
break;
|
||||
return sema_expr_analyse_struct_initializer(context, assigned, expr);
|
||||
case TYPE_ARRAY:
|
||||
TODO
|
||||
case TYPE_VARARRAY:
|
||||
@@ -2075,6 +2196,13 @@ 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_INITIALIZER:
|
||||
// Created during semantic analysis
|
||||
UNREACHABLE
|
||||
case EXPR_RANGE:
|
||||
EXPR_COPY(expr->range_expr.left);
|
||||
EXPR_COPY(expr->range_expr.right);
|
||||
return expr;
|
||||
case EXPR_EXPR_BLOCK:
|
||||
ast_copy_list_from_macro(context, macro, &expr->expr_block.stmts);
|
||||
return expr;
|
||||
@@ -2522,12 +2650,20 @@ EXIT:
|
||||
return success;
|
||||
}
|
||||
|
||||
static inline bool sema_expr_analyse_range(Context *context, Type *to, Expr *expr)
|
||||
{
|
||||
TODO
|
||||
}
|
||||
|
||||
static inline bool sema_analyse_expr_dispatch(Context *context, Type *to, Expr *expr)
|
||||
{
|
||||
switch (expr->expr_kind)
|
||||
{
|
||||
case EXPR_POISONED:
|
||||
return false;
|
||||
case EXPR_DESIGNATED_INITIALIZER:
|
||||
// Created during semantic analysis
|
||||
UNREACHABLE
|
||||
case EXPR_SCOPED_EXPR:
|
||||
UNREACHABLE
|
||||
case EXPR_EXPR_BLOCK:
|
||||
@@ -2536,6 +2672,8 @@ static inline bool sema_analyse_expr_dispatch(Context *context, Type *to, Expr *
|
||||
return sema_expr_analyse_macro_expr(context, to, expr);
|
||||
case EXPR_TRY:
|
||||
return sema_expr_analyse_try(context, to, expr);
|
||||
case EXPR_RANGE:
|
||||
return sema_expr_analyse_range(context, to, expr);
|
||||
case EXPR_CONST:
|
||||
return true;
|
||||
case EXPR_BINARY:
|
||||
|
||||
@@ -92,6 +92,13 @@ void sema_analysis_pass_conditional_compilation(Context *context)
|
||||
DEBUG_LOG("Pass finished with %d error(s).", diagnostics.errors);
|
||||
}
|
||||
|
||||
static inline bool analyse_func_body(Context *context, Decl *decl)
|
||||
{
|
||||
if (!decl->func.body) return true;
|
||||
if (!sema_analyse_function_body(context, decl)) return decl_poison(decl);
|
||||
return true;
|
||||
}
|
||||
|
||||
void sema_analysis_pass_decls(Context *context)
|
||||
{
|
||||
DEBUG_LOG("Pass: Decl analysis %s", context->file->name);
|
||||
@@ -119,5 +126,14 @@ void sema_analysis_pass_decls(Context *context)
|
||||
{
|
||||
sema_analyse_decl(context, context->functions[i]);
|
||||
}
|
||||
VECEACH(context->struct_functions, i)
|
||||
{
|
||||
analyse_func_body(context, context->struct_functions[i]);
|
||||
}
|
||||
VECEACH(context->functions, i)
|
||||
{
|
||||
analyse_func_body(context, context->functions[i]);
|
||||
}
|
||||
|
||||
DEBUG_LOG("Pass finished with %d error(s).", diagnostics.errors);
|
||||
}
|
||||
|
||||
@@ -334,6 +334,27 @@ Type *type_get_meta(Type *meta_type)
|
||||
return type_generate_meta(meta_type, false);
|
||||
}
|
||||
|
||||
Type *type_get_indexed_type(Type *type)
|
||||
{
|
||||
switch (type->type_kind)
|
||||
{
|
||||
case TYPE_POINTER:
|
||||
return type->pointer;
|
||||
case TYPE_VARARRAY:
|
||||
case TYPE_ARRAY:
|
||||
case TYPE_SUBARRAY:
|
||||
return type->array.base;
|
||||
case TYPE_STRING:
|
||||
return type_char;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
Type *canonical = type->canonical;
|
||||
if (canonical != type) return type_get_indexed_type(type);
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
|
||||
Type *type_create_array(Type *arr_type, uint64_t len, bool canonical)
|
||||
{
|
||||
@@ -376,7 +397,7 @@ Type *type_create_array(Type *arr_type, uint64_t len, bool canonical)
|
||||
}
|
||||
Type *array = type_new(TYPE_ARRAY, strformat("%s[%llu]", arr_type->name, len));
|
||||
array->array.base = arr_type;
|
||||
array->array.len = 0;
|
||||
array->array.len = len;
|
||||
if (arr_type->canonical == arr_type)
|
||||
{
|
||||
array->canonical = array;
|
||||
|
||||
Reference in New Issue
Block a user