Support for "static" keyword.

This commit is contained in:
Christoffer Lerno
2021-05-30 16:22:16 +02:00
committed by Christoffer Lerno
parent 0605a8c500
commit dd8b850544
30 changed files with 121 additions and 64 deletions

View File

@@ -21,7 +21,7 @@ color brightred "@\<[A-Za-z_]+\>"
color green "\<(virtual|void|bool|quad|double|float|long|ulong|int|uint|short|ushort|ichar|char|isize|usize|iptr|uptr|iptrdiff|uptrdiff|half)\>"
# Keywords
color yellow "\<(alias|as|asm|assert|attribute|break|case|catch|const|continue|default|defer|define|do|else|enum|extern|error|false|for|foreach|func|generic|if|import|interface|macro|module|nextcase|null|public|return|static|struct|switch|template|true|try|typeid|typeof|union|while|var|volatile)\>"
color yellow "\<(alias|as|asm|assert|attribute|break|case|catch|const|continue|default|defer|define|do|else|enum|extern|error|false|for|foreach|func|generic|if|import|interface|macro|module|nextcase|null|private|return|static|struct|switch|template|true|try|typeid|typeof|union|while|var|volatile)\>"
# Strings
color brightblack "\"[^"]*\""

View File

@@ -359,7 +359,7 @@ bool lexScanNumber(LexInfo *lex) {
}
/** List of all reserved names (excluding literals) */
static VmLiterals ReservedNames[] = {
private VmLiterals ReservedNames[] = {
SymAnd,
SymAsync,
SymBaseurl,

View File

@@ -1,7 +1,7 @@
module std::array::linkedlist<Type>;
import std::mem;
static struct Node
private struct Node
{
Node *next;
Node *prev;
@@ -20,7 +20,7 @@ func void LinkedList.push(LinkedList *list, Type value)
list.linkLast(value);
}
static func void LinkedList.linkFirst(LinkedList *list, Type value)
private func void LinkedList.linkFirst(LinkedList *list, Type value)
{
Node *first = list.first;
Node *new_node = @mem::malloc(Node);
@@ -37,7 +37,7 @@ static func void LinkedList.linkFirst(LinkedList *list, Type value)
list.size++;
}
static func void LinkedList.linkLast(LinkedList *list, Type value)
private func void LinkedList.linkLast(LinkedList *list, Type value)
{
Node *last = list.last;
Node *new_node = mem::alloc(Node.sizeof);
@@ -84,7 +84,7 @@ func Type LinkedList.get(LinkedList* list, usize index)
/**
* @require succ != null
**/
static func void LinkedList.linkBefore(LinkedList *list, Node *succ, Type value)
private func void LinkedList.linkBefore(LinkedList *list, Node *succ, Type value)
{
Node* pred = succ.prev;
Node* new_node = @mem::malloc(Node);
@@ -104,7 +104,7 @@ static func void LinkedList.linkBefore(LinkedList *list, Node *succ, Type value)
/**
* @require f == list.first && f != null
**/
static func void unlinkFirst(LinkedList* list, Node* f)
private func void unlinkFirst(LinkedList* list, Node* f)
{
Node* next = f.next;
mem::free(f);
@@ -123,7 +123,7 @@ static func void unlinkFirst(LinkedList* list, Node* f)
/**
* @require l == list.last && l != null
**/
static func void LinkedList.unlinkLast(LinkedList *list, Node* l)
private func void LinkedList.unlinkLast(LinkedList *list, Node* l)
{
Node* prev = l.prev;
list.last = prev;
@@ -142,7 +142,7 @@ static func void LinkedList.unlinkLast(LinkedList *list, Node* l)
/**
* @require x != null
**/
static func void LinkedList.unlink(LinkedList* list, Node* x)
private func void LinkedList.unlink(LinkedList* list, Node* x)
{
Node* next = x.next;
Node* prev = x.prev;

View File

@@ -8,7 +8,7 @@ struct List
Type *entries;
}
static func void List.ensureCapacity(List *list) @inline
private func void List.ensureCapacity(List *list) @inline
{
if (list.capacity == list.size)
{

View File

@@ -1,6 +1,6 @@
module std::math;
static union DoubleLong
private union DoubleLong
{
double f;
ulong i;
@@ -108,7 +108,7 @@ func double cos_limited(double x, double y)
return w + (((1.0 - w) - hz) + (z*r - x*y));
}
static func double sin_limited(double x, double y, bool iy)
private func double sin_limited(double x, double y, bool iy)
{
const double S1 = -1.66666666666666324348e-01; // 0xBFC55555, 0x55555549
const double S2 = 8.33333333332248946124e-03; // 0x3F811111, 0x1110F8A6

View File

@@ -200,7 +200,7 @@ static void register_generic_decls(Module *module, Decl **decls)
}
static void analyze_generic_module(Module *module)
{
assert(module->parameters);
assert(module->parameters && module->is_generic);
// TODO maybe do this analysis: sema_analysis_pass_process_imports(module);
VECEACH(module->contexts, index)
{
@@ -508,6 +508,7 @@ Module *compiler_find_or_create_module(Path *module_name, TokenId *parameters, b
module->name = module_name;
module->stage = ANALYSIS_NOT_BEGUN;
module->parameters = parameters;
module->is_generic = vec_size(parameters) > 0;
module->is_private = is_private;
stable_init(&module->symbols, 0x10000);
stable_set(&global_context.modules, module_name->module, module);

View File

@@ -340,9 +340,9 @@ void llvm_emit_ptr_from_array(GenContext *c, BEValue *value)
UNREACHABLE
}
}
static void gencontext_emit_global_variable_init(GenContext *c, Decl *decl)
void llvm_emit_global_variable_init(GenContext *c, Decl *decl)
{
assert(decl->var.kind == VARDECL_GLOBAL || decl->var.kind == VARDECL_CONST);
assert(decl->var.kind == VARDECL_GLOBAL || decl->var.kind == VARDECL_CONST || decl->var.is_static);
// Skip real constants.
if (!decl->type) return;
@@ -475,6 +475,8 @@ void llvm_emit_and_set_decl_alloca(GenContext *c, Decl *decl)
void llvm_emit_local_var_alloca(GenContext *c, Decl *decl)
{
assert(!decl->var.is_static);
printf("My name %s\n", decl->name);
llvm_emit_and_set_decl_alloca(c, decl);
if (llvm_use_debug(c))
{
@@ -981,7 +983,7 @@ void *llvm_gen(Module *module)
}
VECEACH(context->vars, i)
{
gencontext_emit_global_variable_init(gen_context, context->vars[i]);
llvm_emit_global_variable_init(gen_context, context->vars[i]);
}
VECEACH(context->functions, i)
{

View File

@@ -232,13 +232,14 @@ void llvm_emit_defer(GenContext *c, AstId defer_start, AstId defer_end);
void llvm_emit_extern_decl(GenContext *context, Decl *decl);
LLVMValueRef llvm_emit_const_aggregate(GenContext *c, Expr *expr, bool *modified);
void llvm_emit_expr(GenContext *c, BEValue *value, Expr *expr);
void llvm_emit_global_variable_init(GenContext *c, Decl *decl);
LLVMValueRef llvm_emit_int_comparison(GenContext *c, Type *lhs_type, Type *rhs_type, LLVMValueRef lhs_value, LLVMValueRef rhs_value, BinaryOp binary_op);
LLVMValueRef llvm_emit_is_no_error_value(GenContext *c, BEValue *value);
void llvm_emit_len_for_expr(GenContext *c, BEValue *be_value, BEValue *expr_to_len);
LLVMValueRef llvm_emit_load_aligned(GenContext *c, LLVMTypeRef type, LLVMValueRef pointer, AlignSize alignment, const char *name);
void llvm_emit_local_var_alloca(GenContext *c, Decl *decl);
void llvm_emit_expr(GenContext *c, BEValue *value, Expr *expr);
LLVMValueRef llvm_emit_memclear_size_align(GenContext *c, LLVMValueRef ref, uint64_t size, unsigned align, bool bitcast);
LLVMValueRef llvm_emit_memclear(GenContext *c, BEValue *ref);
void llvm_emit_memcpy(GenContext *c, LLVMValueRef dest, unsigned dest_align, LLVMValueRef source, unsigned src_align, uint64_t len);

View File

@@ -44,12 +44,25 @@ static LLVMValueRef llvm_emit_decl(GenContext *c, Ast *ast)
Decl *decl = ast->declare_stmt;
LLVMTypeRef alloc_type = llvm_get_type(c, type_lowering(decl->type));
if (decl->var.is_static)
{
decl->backend_ref = LLVMAddGlobal(c->module, llvm_get_type(c, decl->type), "tempglobal");
llvm_emit_global_variable_init(c, decl);
if (decl->var.failable)
{
decl->var.failable_ref = LLVMAddGlobal(c->module, llvm_get_type(c, type_error), decl->name);
LLVMBuildStore(c->builder, LLVMConstNull(llvm_get_type(c, type_error)), decl->var.failable_ref);
}
return decl->backend_ref;
}
llvm_emit_local_var_alloca(c, decl);
if (decl->var.failable)
{
decl->var.failable_ref = llvm_emit_alloca_aligned(c, type_error, decl->name);
LLVMBuildStore(c->builder, LLVMConstNull(llvm_get_type(c, type_error)), decl->var.failable_ref);
}
Expr *init = decl->var.init_expr;
if (init)
{

View File

@@ -71,7 +71,7 @@ void recover_top_level(Context *context)
{
switch (context->tok.type)
{
case TOKEN_STATIC:
case TOKEN_PRIVATE:
case TOKEN_STRUCT:
case TOKEN_INTERFACE:
case TOKEN_IMPORT:
@@ -800,6 +800,8 @@ Decl *parse_decl(Context *context)
return parse_const_declaration(context, VISIBLE_LOCAL);
}
bool is_static = try_consume(context, TOKEN_STATIC);
TypeInfo *type = TRY_TYPE_OR(parse_type(context), poisoned_decl);
bool failable = try_consume(context, TOKEN_BANG);
@@ -811,7 +813,11 @@ Decl *parse_decl(Context *context)
return poisoned_decl;
}
decl->var.failable = failable;
decl->var.is_static = is_static;
if (is_static)
{
printf("Added static to %s %d\n", decl->name, decl->var.is_static);
}
return decl;
}
@@ -2239,7 +2245,7 @@ Decl *parse_top_level_statement(Context *context)
Visibility visibility = VISIBLE_PUBLIC;
switch (context->tok.type)
{
case TOKEN_STATIC:
case TOKEN_PRIVATE:
visibility = VISIBLE_MODULE;
advance(context);
break;

View File

@@ -19,7 +19,6 @@ static inline Ast *parse_declaration_stmt(Context *context)
{
Ast *decl_stmt = AST_NEW_TOKEN(AST_DECLARE_STMT, context->tok);
decl_stmt->declare_stmt = TRY_DECL_OR(parse_decl(context), poisoned_ast);
decl_stmt->declare_stmt->var.is_static = try_consume(context, TOKEN_STATIC);
CONSUME_OR(TOKEN_EOS, poisoned_ast);
return decl_stmt;
}

View File

@@ -700,7 +700,7 @@ static AttributeType sema_analyse_attribute(Context *context, Attr *attr, Attrib
return type;
case ATTRIBUTE_SECTION:
case ATTRIBUTE_CNAME:
if (context->module->parameters)
if (context->module->is_generic)
{
SEMA_TOKID_ERROR(attr->name, "'cname' attributes are not allowed in generic modules.");
return false;

View File

@@ -67,7 +67,7 @@ static Decl *sema_resolve_path_symbol(Context *context, const char *symbol, Path
{
Decl *import = context->imports[i];
if (import->module->parameters) continue;
if (import->module->is_generic) continue;
// 4. Can we match a subpath?
if (path->len > import->import.path->len) continue;
@@ -140,7 +140,7 @@ static Decl *sema_resolve_no_path_symbol(Context *context, const char *symbol,
if (!decl_ok(import)) continue;
// Skip parameterized modules
if (import->module->parameters) continue;
if (import->module->is_generic) continue;
Decl *found = module_find_symbol(import->module, symbol);
if (!found) continue;
@@ -242,7 +242,6 @@ Decl *sema_resolve_parameterized_symbol(Context *context, TokenId symbol, Path *
{
Decl *ambiguous_other_decl = NULL;
Decl *private_decl = NULL;
bool path_found = false;
Decl *decl = NULL;
const char *symbol_str = TOKSTR(symbol);
if (path)
@@ -253,14 +252,12 @@ Decl *sema_resolve_parameterized_symbol(Context *context, TokenId symbol, Path *
Decl *import = context->imports[i];
// Skip any without parameters.
if (!import->module->parameters) continue;
if (!import->module->is_generic) continue;
// 5. Can we match a subpath?
if (path->len > import->import.path->len) continue;
if (!matches_subpath(import->import.path, path)) continue;
// 6. We have a sub path match at least.
path_found = true;
// 7. Find the symbol
Decl *found = module_find_symbol(import->module, symbol_str);
@@ -302,7 +299,7 @@ Decl *sema_resolve_parameterized_symbol(Context *context, TokenId symbol, Path *
Decl *import = context->imports[i];
// Skip any without parameters.
if (!import->module->parameters) continue;
if (!import->module->is_generic) continue;
// 7. Find the symbol
Decl *found = module_find_symbol(import->module, symbol_str);

View File

@@ -508,8 +508,25 @@ static inline bool sema_analyse_local_decl(Context *context, Decl *decl)
SEMA_ERROR(decl->var.init_expr, "A failable expression was expected here.");
return decl_poison(decl);
}
}
EXIT_OK:
if (decl->var.is_static)
{
scratch_buffer_clear();
scratch_buffer_append(context->active_function_for_analysis->name);
scratch_buffer_append_char('.');
scratch_buffer_append(decl->name);
decl->external_name = scratch_buffer_interned();
}
if (decl->var.init_expr && decl->var.is_static)
{
if (!expr_is_constant_eval(decl->var.init_expr))
{
SEMA_ERROR(decl->var.init_expr, "Static variable initialization must be constant.");
return false;
}
}
if (!decl->alignment) decl->alignment = type_alloca_alignment(decl->type);
return true;
}

View File

@@ -1 +1 @@
#define COMPILER_VERSION "A225"
#define COMPILER_VERSION "A226"

View File

@@ -6,7 +6,7 @@ struct Foo
int x, y;
}
static Foo[10] array;
private Foo[10] array;
// #expect: test.ll

View File

@@ -8,7 +8,7 @@ struct Connection
long length;
}
static Connection[3] link
private Connection[3] link
= { {1, "link1", 10},
{2, "link2", 20},
{3, "link3", 30} };

View File

@@ -1,15 +1,15 @@
static const char AA = ~(char)(0);
private const char AA = ~(char)(0);
const char BB = 200 ;
static const uint CC = ~(uint)(0);
static const uint DD = FOO;
private const uint CC = ~(uint)(0);
private const uint DD = FOO;
static const FOO = ~(uint)(0);
private const FOO = ~(uint)(0);
static uint x = AA;
static uint z = CC;
static char w = (char)(FOO);
static ushort v = (ushort)(FOO);
static uint z2 = DD;
private uint x = AA;
private uint z = CC;
private char w = (char)(FOO);
private ushort v = (ushort)(FOO);
private uint z2 = DD;
func void test()
{

View File

@@ -0,0 +1,20 @@
module foo;
func int test()
{
static int x = 1;
x++;
return x;
}
// #expect: foo.ll
@test.x = hidden global i32 1, align 4
define i32 @foo.test()
%0 = load i32, i32* @test.x, align 4
%add = add i32 %0, 1
store i32 %add, i32* @test.x, align 4
%1 = load i32, i32* @test.x, align 4
ret i32 %1

View File

@@ -0,0 +1 @@
static int ifej; // #error: Expected a top level declaration here

View File

@@ -4,7 +4,7 @@ macro int cofefe(#a)
return #a + #a;
}
static int abc = 1;
private int abc = 1;
func int xx()
{

View File

@@ -2,11 +2,11 @@
module const_pointer;
static double foo = 17;
static double bar = 12.0;
static float xx = 12.0;
private double foo = 17;
private double bar = 12.0;
private float xx = 12.0;
static void*[3] data = { &foo, &bar, &xx };
private void*[3] data = { &foo, &bar, &xx };
// #expect: const_pointer.ll

View File

@@ -1,6 +1,6 @@
module test;
static Foo a;
private Foo a;
struct Foo
{

View File

@@ -6,16 +6,16 @@ struct Foo
long bar;
}
static usize x = Foo.sizeof;
private usize x = Foo.sizeof;
static Foo foo1 = { 1, 2 };
static Foo foo2 = { .foo = 2 };
static Foo foo3 = { .bar = 3 };
static Foo foo4 = { .bar = 4, .foo = 4, .bar = 1 };
static Foo foo5 = {};
static Foo foo6;
static const Foo FOO7 = { 1, 2 };
static Foo foo8 = FOO7;
private Foo foo1 = { 1, 2 };
private Foo foo2 = { .foo = 2 };
private Foo foo3 = { .bar = 3 };
private Foo foo4 = { .bar = 4, .foo = 4, .bar = 1 };
private Foo foo5 = {};
private Foo foo6;
private const Foo FOO7 = { 1, 2 };
private Foo foo8 = FOO7;
// #expect: structo.ll

View File

@@ -6,9 +6,9 @@ union Foo
double b;
}
static Foo f = { .a = 23 };
static Foo g = { .b = 2.3 };
static Foo h = { .a = 23, .b = 2.3 };
private Foo f = { .a = 23 };
private Foo g = { .b = 2.3 };
private Foo h = { .a = 23, .b = 2.3 };
Foo i = { .b = 2.3, .a = 23 };
// #expect: test.ll

View File

@@ -17,7 +17,7 @@ import bar;
int a;
static func void test2()
private func void test2()
{
int c = a; // This is fine.
c = foo::b;

View File

@@ -11,7 +11,7 @@ func void runBar()
module baz;
import bar;
static func void visible()
private func void visible()
{
bar::barFunc();
}

View File

@@ -10,7 +10,7 @@ func void runBar()
// #file: file2.c3
module bar;
static func void notVisible()
private func void notVisible()
{
}

View File

@@ -1,6 +1,6 @@
module foo;
static func void hidden()
private func void hidden()
{
}

View File

@@ -9,7 +9,7 @@ func void runBar()
// #file: file2.c3
module baz;
static func void visible()
private func void visible()
{
}