Recursive references between globals are now correctly handled.

This commit is contained in:
Christoffer Lerno
2021-01-24 22:53:46 +01:00
committed by Christoffer Lerno
parent 7fc12192f4
commit 26d25e3f74
25 changed files with 75 additions and 163 deletions

View File

@@ -115,15 +115,14 @@ public func int! decode(char[] in, byte* out)
}
extern func void printf(char *fmt, ...);
public func void main()
{
printf("Startin...\n");
char *helloworld = "Hello World\n";
char[1000] buffer;
encode(cast(helloworld as byte*)[0..12], &buffer);
printf("Printres\n");
printf("Result: %s\n", &buffer);
char *to_decode = "aGVsbG8gd29ybGRcMA==";
decode(to_decode[0..19], cast(&buffer as byte*));
printf("2Result: %s\n", &buffer);
printf("Result: %s\n", &buffer);
}

View File

@@ -1,2 +1,3 @@
module std:cinterop;

View File

@@ -1,27 +0,0 @@
module foo;
public struct Foo
{
int i;
}
public func int Foo.test(Foo *foo)
{
if (!foo) return 0;
return foo.i;
}
public func void gonk()
{
Foo.test(null);
printf("Bob\n");
}
func void test()
{
int i = 0;
}
func void main()
{
printf("Helo\n");
}

View File

@@ -1,13 +0,0 @@
module bar;
import foo local;
func void test()
{
int i = 0;
}
func void main()
{
gonk();
printf("Helo\n");
}

View File

@@ -1,51 +0,0 @@
struct Foo
{
int x;
struct b
{
int y;
int z;
}
struct
{
int g;
}
union
{
usize x1;
int z2;
}
}
func void Foo.xy(Foo* f, int y)
{
f.b.y = y;
}
extern func void printf(char*c , ...);
struct SimpleStruct
{
int a;
double b;
}
func void main()
{
Foo z;
z.x = 2;
z.b.z = 3;
z.g = 4;
printf("z.x = %d\n", z.x);
printf("z.b.z = %d\n", z.b.z);
printf("z.g = %d\n", z.g);
z.xy(100);
printf("z.b.y = %d\n", z.b.y);
SimpleStruct s = { a = 3, b = 33.3 };
int[2] fe = { 1, 2 };
//Foo f = { x = 2, b.z = 3, z2 = -2 };
Foo f = { x = 2, b.z = 3, z2 = -2, b = { 1, 4 } };
int[3] fo = { [1] = 2 };
//byte[7] fo = { [1..4] = 3 };
}

View File

@@ -1,18 +0,0 @@
module struct2;
struct Blend_Map_Entry
{
union vals {
float[5] colour;
double[2] point_Slope;
}
}
Blend_Map_Entry a = { .vals = { .colour = { 1, 2, 3, 4, 5 } } };
Blend_Map_Entry b = { .vals = { .point_Slope = { 6, 7 } } };
Blend_Map_Entry c = { .vals.colour[2] = 1 };
Blend_Map_Entry d = { .vals.colour = { 1, 2, 3, 4, 5 } };
func void test(Blend_Map_Entry* foo)
{
}

View File

@@ -1,5 +0,0 @@
module typedefs;
typedef Loop as Loop2;
typedef Loop2 as Loop3;
typedef Loop3 as Loop;

View File

@@ -1,14 +0,0 @@
module typedefs;
// Standard case
typedef int as Foo;
// Nested resolution
typedef AType as BType;
typedef int as AType;
enum Bar : BType
{
A,
B
}

View File

@@ -291,10 +291,22 @@ static void gencontext_emit_global_variable_definition(GenContext *c, Decl *decl
// Skip real constants.
if (!decl->type) return;
decl->backend_ref = LLVMAddGlobal(c->module, llvm_get_type(c, decl->type), "tempglobal");
}
static void gencontext_emit_global_variable_init(GenContext *c, Decl *decl)
{
assert(decl->var.kind == VARDECL_GLOBAL || decl->var.kind == VARDECL_CONST);
// Skip real constants.
if (!decl->type) return;
bool modified = false;
LLVMValueRef init_value;
ByteSize alignment = type_abi_alignment(decl->type);
if (decl->var.init_expr)
{
if (decl->var.init_expr->expr_kind == EXPR_INITIALIZER_LIST)
@@ -315,6 +327,7 @@ static void gencontext_emit_global_variable_definition(GenContext *c, Decl *decl
}
// TODO fix name
LLVMValueRef old = decl->backend_ref;
decl->backend_ref = LLVMAddGlobal(c->module, LLVMTypeOf(init_value), decl->name);
LLVMSetAlignment(decl->backend_ref, alignment);
if (decl->visibility != VISIBLE_EXTERN)
@@ -345,6 +358,8 @@ static void gencontext_emit_global_variable_definition(GenContext *c, Decl *decl
{
decl->backend_ref = LLVMConstBitCast(decl->backend_ref, llvm_get_ptr_type(c, decl->type));
}
LLVMReplaceAllUsesWith(old, decl->backend_ref);
// Should we set linkage here?
if (llvm_use_debug(c))
{
@@ -880,6 +895,10 @@ void *llvm_gen(Context *context)
{
gencontext_emit_global_variable_definition(gen_context, context->vars[i]);
}
VECEACH(context->vars, i)
{
gencontext_emit_global_variable_init(gen_context, context->vars[i]);
}
VECEACH(context->functions, i)
{
Decl *decl = context->functions[i];

View File

@@ -807,38 +807,7 @@ static inline bool sema_analyse_global(Context *context, Decl *decl)
if (!sema_resolve_type_info(context, decl->var.type_info)) return false;
decl->type = decl->var.type_info->type;
}
// Check the initializer.
if (decl->var.init_expr && decl->type)
{
Expr *init_expr = decl->var.init_expr;
// 1. Check type.
if (!sema_analyse_expr_of_required_type(context, decl->type, init_expr, false)) return false;
// 2. Check const-ness
if (!init_expr->constant)
{
// 3. Special case is when the init expression is the reference
// to a constant global structure.
if (init_expr->expr_kind == EXPR_CONST_IDENTIFIER)
{
// 4. If so we copy the init expression, which should always be constant.
*init_expr = *init_expr->identifier_expr.decl->var.init_expr;
assert(init_expr->constant);
}
else
{
if (init_expr->expr_kind == EXPR_CAST)
{
SEMA_ERROR(decl->var.init_expr, "The expression may not be a non constant cast.");
}
else
{
SEMA_ERROR(decl->var.init_expr, "The expression must be a constant value.");
}
return false;
}
}
if (!decl->type) decl->type = decl->var.init_expr->type;
}
// We expect a constant to actually be parsed correctly so that it has a value, so
// this should always be true.
assert(decl->type || decl->var.kind == VARDECL_CONST);
@@ -879,6 +848,45 @@ static inline bool sema_analyse_global(Context *context, Decl *decl)
}
}
// If we already have the type resolved then we can pretend to be done,
// this will help in case we otherwise would get circular references.
if (decl->type)
{
decl->resolve_status = RESOLVE_DONE;
}
// Check the initializer.
if (decl->var.init_expr && decl->type)
{
Expr *init_expr = decl->var.init_expr;
// 1. Check type.
if (!sema_analyse_expr_of_required_type(context, decl->type, init_expr, false)) return false;
// 2. Check const-ness
if (!init_expr->constant)
{
// 3. Special case is when the init expression is the reference
// to a constant global structure.
if (init_expr->expr_kind == EXPR_CONST_IDENTIFIER)
{
// 4. If so we copy the init expression, which should always be constant.
*init_expr = *init_expr->identifier_expr.decl->var.init_expr;
assert(init_expr->constant);
}
else
{
if (init_expr->expr_kind == EXPR_CAST)
{
SEMA_ERROR(decl->var.init_expr, "The expression may not be a non constant cast.");
}
else
{
SEMA_ERROR(decl->var.init_expr, "The expression must be a constant value.");
}
return false;
}
}
}
switch (decl->var.kind)
{
case VARDECL_CONST:

View File

@@ -4011,6 +4011,7 @@ static inline bool sema_take_addr_of_var(Expr *expr, Decl *decl, bool *is_consta
case VARDECL_PARAM_REF:
return true;
case VARDECL_CONST:
*is_constant = true;
if (!decl->var.type_info)
{
SEMA_ERROR(expr, "The constant is not typed, either type it or use && to take the reference to a temporary.");

View File

@@ -0,0 +1,12 @@
struct List
{
int x;
List* next;
}
local const List A = { 7, &B };
local const List B = { 8, &A };
extern List d;
List c = { 7, &d };