diff --git a/analyser/conversion_checker.c2 b/analyser/conversion_checker.c2 index 95237d23c..00972bac2 100644 --- a/analyser/conversion_checker.c2 +++ b/analyser/conversion_checker.c2 @@ -118,7 +118,7 @@ public type Checker struct { public fn void Checker.init(Checker* c, diagnostics.Diags* diags, ast_builder.Builder* builder) { c.diags = diags; c.builder = builder; - c.native_kind = ast.getNativeKind(); + c.native_kind = builder.getNativeKind(); // leave other fields uninitialized } diff --git a/analyser/conversion_checker_expr.c2 b/analyser/conversion_checker_expr.c2 index 9fb04f7d6..7b9d9725d 100644 --- a/analyser/conversion_checker_expr.c2 +++ b/analyser/conversion_checker_expr.c2 @@ -128,9 +128,6 @@ fn ExprWidth getUnaryOpWidth(const UnaryOperator* u) { // TODO adjust for integer promotion? return getExprWidth(u.getInner()); case AddrOf: - w.width = (u8)(ast.getWordSize() * 8); - w.is_signed = false; - break; case Deref: Expr* e = (Expr*)u; return getTypeWidth(e.getType()); @@ -228,7 +225,7 @@ fn ExprWidth getTypeWidth(QualType qt) { return result; } // pointer or something - ExprWidth result = { .width = (u8)(ast.getWordSize() * 8), .is_signed = false } + ExprWidth result = { .width = (u8)(qt.getAlignment() * 8), .is_signed = false } return result; } diff --git a/analyser/size_analyser.c2 b/analyser/size_analyser.c2 index 4b490980c..c1eec6fa9 100644 --- a/analyser/size_analyser.c2 +++ b/analyser/size_analyser.c2 @@ -185,21 +185,20 @@ public fn TypeSize sizeOfType(QualType qt) { if (qt.isInvalid()) return result; - u32 pointerSize = getWordSize(); - qt = qt.getCanonicalType(); Type* t = qt.getType(); switch (t.getKind()) { case Builtin: const BuiltinType* bi = (BuiltinType*)t; // NOTE: alignment is also size - result.size = bi.getAlignment(); - result.align = result.size; + result.align = bi.getAlignment(); + result.size = result.align; result.is_signed = bi.isSigned(); break; case Pointer: - result.size = pointerSize; - result.align = result.size; + case Function: + result.align = t.getAlignment(); + result.size = result.align; break; case Array: ArrayType* arrayType = (ArrayType*)t; @@ -218,10 +217,6 @@ public fn TypeSize sizeOfType(QualType qt) { EnumType* et = (EnumType*)t; EnumTypeDecl* etd = et.getDecl(); return sizeOfType(etd.getImplType()); - case Function: - result.size = pointerSize; - result.align = pointerSize; - break; case Void: result.size = 0; result.align = 0; diff --git a/ast/builtin_type.c2 b/ast/builtin_type.c2 index 440405f80..dea5a9572 100644 --- a/ast/builtin_type.c2 +++ b/ast/builtin_type.c2 @@ -24,10 +24,10 @@ public type BuiltinKind enum u8 (public const char* const name, const bool is_signed, const bool is_unsigned, const bool is_integer, - const u8 default_size, - const u8 default_width) + const u8 align, + const u8 width) { - // Note: default_size/width is adjusted for 32-bit in globals + // Note: align/width is adjusted for 32-bit in globals Char : { "char", true, false, true, true, 1, 8 }, Int8 : { "i8", true, true, false, true, 1, 8 }, Int16 : { "i16", true, true, false, true, 2, 16 }, @@ -39,17 +39,16 @@ public type BuiltinKind enum u8 (public const char* const name, UInt64 : { "u64", false, false, true, true, 8, 64 }, Float32 : { "f32", false, true, false, false, 4, 0 }, Float64 : { "f64", false, true, false, false, 8, 0 }, - ISize : { "isize", false, true, false, true, 8, 64 }, - USize : { "usize", false, false, true, true, 8, 64 }, + ISize : { "isize", false, true, false, true, 0, 0 }, + USize : { "usize", false, false, true, true, 0, 0 }, Bool : { "bool", true, false, false, false, 1, 1 }, } type BuiltinTypeBits struct { - u32 : NumTypeBits; // : 8 + u32 : NumTypeBits; // : 16 BuiltinKind kind : 4; BuiltinKind base_kind : 4; u32 width : 8; - u32 size : 8; } static_assert(sizeof(BuiltinTypeBits), 4); @@ -57,16 +56,16 @@ public type BuiltinType struct @(opaque) { Type base; } -fn BuiltinType* BuiltinType.create(ast_context.Context* c, BuiltinKind kind, u32 wordsize) { +fn BuiltinType* BuiltinType.create(ast_context.Context* c, BuiltinKind kind) { + BuiltinKind base_kind = kind; + if (kind == ISize) base_kind = (c.getWordSize() == 4) ? Int32 : Int64; + if (kind == USize) base_kind = (c.getWordSize() == 4) ? UInt32 : UInt64; BuiltinType* b = c.alloc(sizeof(BuiltinType)); b.base.init(Builtin); - BuiltinKind base_kind = kind; - if (kind == ISize) base_kind = (wordsize == 4) ? Int32 : Int64; - if (kind == USize) base_kind = (wordsize == 4) ? UInt32 : UInt64; b.base.builtinTypeBits.kind = kind; b.base.builtinTypeBits.base_kind = base_kind; - b.base.builtinTypeBits.width = base_kind.default_width; - b.base.builtinTypeBits.size = base_kind.default_size; + b.base.builtinTypeBits.width = base_kind.width; + b.base.setAlignment(base_kind.align); b.base.setCanonicalType(QualType.create(&b.base)); #if AstStatistics Stats.addType(Builtin, sizeof(BuiltinType)); @@ -120,7 +119,7 @@ public fn bool BuiltinType.isUnsigned(const BuiltinType* b) { } public fn u32 BuiltinType.getAlignment(const BuiltinType* b) { - return b.base.builtinTypeBits.size; + return b.base.typeBits.align; } public fn u32 BuiltinType.getWidth(const BuiltinType* b) { diff --git a/ast/function_type.c2 b/ast/function_type.c2 index a044d3140..be2cd28f8 100644 --- a/ast/function_type.c2 +++ b/ast/function_type.c2 @@ -26,6 +26,7 @@ public type FunctionType struct @(opaque) { fn FunctionType* FunctionType.create(ast_context.Context* c, FunctionDecl* decl) { FunctionType* t = c.alloc(sizeof(FunctionType)); t.base.init(Function); + t.base.setAlignment(c.getWordSize()); t.decl = decl; t.base.setCanonicalType(QualType.create(&t.base)); diff --git a/ast/pointer_pool.c2 b/ast/pointer_pool.c2 index d0331386e..f58255db4 100644 --- a/ast/pointer_pool.c2 +++ b/ast/pointer_pool.c2 @@ -42,11 +42,12 @@ type PointerPool struct { } fn void PointerPool.init(PointerPool* p, ast_context.Context* c) { + p.context = c; p.count = 1; // skip first slot p.capacity = 0; p.slots = nil; - p.context = c; p.resize(64); + memset(p.slots, 0, sizeof(p.slots[0])); } fn void PointerPool.clear(PointerPool* p) { diff --git a/ast/pointer_type.c2 b/ast/pointer_type.c2 index d08343011..601b64c5e 100644 --- a/ast/pointer_type.c2 +++ b/ast/pointer_type.c2 @@ -27,6 +27,7 @@ public type PointerType struct @(opaque) { fn PointerType* PointerType.create(ast_context.Context* c, QualType inner) { PointerType* t = c.alloc(sizeof(PointerType)); t.base.init(Pointer); + t.base.setAlignment(c.getWordSize()); t.inner = inner; #if AstStatistics Stats.addType(Pointer, sizeof(PointerType)); diff --git a/ast/type.c2 b/ast/type.c2 index 064e49fac..da3f3d5b3 100644 --- a/ast/type.c2 +++ b/ast/type.c2 @@ -31,8 +31,9 @@ public type TypeKind enum u8 (const char* const name) { type TypeBits struct { TypeKind kind : 8; + u32 align : 8; } -const u32 NumTypeBits = 8; +const u32 NumTypeBits = 16; public type Type struct @(opaque) { union { @@ -48,6 +49,7 @@ public type Type struct @(opaque) { fn void Type.init(Type* t, TypeKind k) { t.bits = 0; t.typeBits.kind = k; + t.typeBits.align = 0; t.ptr_pool_idx = 0; t.canonicalType.ptr = 0; } @@ -101,13 +103,16 @@ public fn void Type.dump(const Type* t) @(unused) { ast.flushDumpBuf(out); } -fn u32 Type.getAlignment(const Type* t) { +fn void Type.setAlignment(Type* t, u32 align) { + t.typeBits.align = align; +} + +public fn u32 Type.getAlignment(const Type* t) { switch (t.getKind()) { case Builtin: - const BuiltinType* bi = (BuiltinType*)t; - return bi.getAlignment(); case Pointer: - break; + case Function: + return t.typeBits.align; case Array: const ArrayType* at = (ArrayType*)t; QualType elem = at.getElemType(); @@ -121,8 +126,6 @@ fn u32 Type.getAlignment(const Type* t) { const EnumTypeDecl* etd = e.getDecl(); QualType it = etd.getImplType(); return it.getTypeOrNil().getAlignment(); - case Function: - break; case Void: return 0; case Alias: @@ -132,7 +135,7 @@ fn u32 Type.getAlignment(const Type* t) { // should not happen return 0; } - return getWordSize(); + return 0; } fn u32 Type.getElemSize(const Type* t) { @@ -159,7 +162,8 @@ fn u32 Type.getSize(const Type* t) { const BuiltinType* bi = (BuiltinType*)t; return bi.getAlignment(); // note: alignment is size case Pointer: - break; + case Function: + return t.getAlignment(); case Array: const ArrayType* at = (ArrayType*)t; QualType elem = at.getElemType(); @@ -173,8 +177,6 @@ fn u32 Type.getSize(const Type* t) { const EnumTypeDecl* etd = e.getDecl(); QualType it = etd.getImplType(); return it.getSize(); - case Function: - break; case Void: return 0; case Alias: @@ -184,7 +186,7 @@ fn u32 Type.getSize(const Type* t) { // should not happen return 0; } - return getWordSize(); + return 0; } fn void Type.print(const Type* t, string_buffer.Buf* out) { diff --git a/ast/utils.c2 b/ast/utils.c2 index 22ca850dc..92d488265 100644 --- a/ast/utils.c2 +++ b/ast/utils.c2 @@ -105,7 +105,6 @@ public type Globals struct @(opaque) { string_pool.Pool* names_pool; PointerPool pointers; StringTypePool string_types; - u32 wordsize; // 4 or 8 (in bytes) bool use_color; // TODO just use AST vector (also in modules, but modules has ownership) u32 ast_count; // Note: first index used to indicate nil @@ -127,11 +126,10 @@ public fn Globals* getGlobals() { return globals; } public fn void setGlobals(Globals* g) @(unused) { globals = g; } // wordsize in bytes, must NOT be called from Plugin! -public fn void initialize(Context* c, string_pool.Pool* astPool, u32 wordsize, bool use_color) { +public fn void initialize(Context* c, string_pool.Pool* astPool, bool use_color) { Globals* g = stdlib.calloc(sizeof(Globals), 1); g.pointers.init(c); g.string_types.init(c); - g.wordsize = wordsize; g.use_color = use_color; g.names_pool = astPool; g.ast_count = 1; @@ -145,7 +143,7 @@ public fn void initialize(Context* c, string_pool.Pool* astPool, u32 wordsize, b // create all Qualtypes for builtin-types for (BuiltinKind kind = BuiltinKind.min; kind <= BuiltinKind.max; kind++) { - g.builtins[kind].set((Type*)BuiltinType.create(c, kind, wordsize)); + g.builtins[kind].set((Type*)BuiltinType.create(c, kind)); } // create void type and void-ptr type @@ -180,10 +178,6 @@ public fn void deinit() { globals = nil; } -public fn u32 getWordSize() { - return globals.wordsize; -} - public fn bool useColor() @(unused) { return globals.use_color; } @@ -257,10 +251,6 @@ fn void flushDumpBuf(string_buffer.Buf* out) { out.clear(); } -public fn BuiltinKind getNativeKind() { - return globals.wordsize == 8 ? UInt64 : UInt32; -} - Color col_Stmt = Color.Bmagenta; Color col_Decl = Color.Bgreen; Color col_Expr = Color.Bmagenta; diff --git a/ast_utils/context.c2 b/ast_utils/context.c2 index 7765641c7..8a482c954 100644 --- a/ast_utils/context.c2 +++ b/ast_utils/context.c2 @@ -45,7 +45,7 @@ fn Block* Block.free(Block* b) { return next; } -public type Context struct @(opaque) { +type TailAllocator struct { Block* blk_head; Block* blk_tail; u32 blk_size; @@ -55,7 +55,7 @@ public type Context struct @(opaque) { u32 cur_allocated; } -fn void Context.init(Context* c, u32 blk_size) { +fn void TailAllocator.init(TailAllocator* c, u32 blk_size) { c.blk_head = nil; c.blk_tail = nil; c.blk_size = blk_size >= 1024 ? blk_size - sizeof(Block) : blk_size; @@ -65,31 +65,13 @@ fn void Context.init(Context* c, u32 blk_size) { c.cur_allocated = 0; } -public fn Context* create(u32 blk_size) { - Context* c = malloc(sizeof(Context)); - c.init(blk_size); - return c; -} - -fn void Context.freeBlocks(Context* c) { +fn void TailAllocator.freeBlocks(TailAllocator* c) { Block* blk = c.blk_head; while (blk) blk = blk.free(); c.blk_head = c.blk_tail = nil; } -public fn void Context.free(Context* c) { - c.freeBlocks(); - free(c); -} - -/* -public fn void Context.clear(Context* c) { - c.freeBlocks(); - c.init(); -} -*/ - -public fn void* Context.alloc(Context* c, u32 len) { +fn void* TailAllocator.alloc(TailAllocator* c, u32 len) { len = (len + 7) & ~0x7; // always round to 8-byte boundaries c.num_allocs++; @@ -116,7 +98,7 @@ public fn void* Context.alloc(Context* c, u32 len) { #if 0 // Make sure len bytes fit sequentially, does NOT allocate! -public fn void Context.reserve(Context* c, u32 len) { +public fn void TailAllocator.reserve(TailAllocator* c, u32 len) { len = (len + 7) & ~0x7; // always round to 8-byte boundaries c.alloc(len); c.num_allocs--; @@ -124,7 +106,7 @@ public fn void Context.reserve(Context* c, u32 len) { } #endif -public fn void Context.report(const Context* c) { +fn void TailAllocator.report(const TailAllocator* c) { u32 blocks = 0; u32 total = 0; u32 slack = 0; @@ -141,3 +123,41 @@ public fn void Context.report(const Context* c) { stdio.printf("context: %d allocs, total %d (%d KB), avg %d bytes, %d blocks (%d), slack %d, avail %d\n", c.num_allocs, total, (total + 1023) / 1024, avg, blocks, c.blk_size, slack, avail); } + +// TODO: rename this AstContext and move to ast module + +public type Context struct @(opaque) { + TailAllocator allocator; + u32 blk_size; + u32 wordsize; +} + +public fn Context* create(u32 blk_size, u32 wordsize) { + Context* c = malloc(sizeof(Context)); + c.allocator.init(blk_size); + c.blk_size = blk_size; + c.wordsize = wordsize; + return c; +} + +public fn void Context.free(Context* c) { + c.allocator.freeBlocks(); + free(c); +} + +#if 0 +public fn void Context.clear(Context* c) { + c.allocator.freeBlocks(); + c.allocator.init(c.blk_size); +} +#endif + +public fn u32 Context.getWordSize(Context* c) { return c.wordsize; } + +public fn void* Context.alloc(Context* c, u32 len) { + return c.allocator.alloc(len); +} + +public fn void Context.report(Context* c) { + c.allocator.report(); +} diff --git a/common/ast_builder.c2 b/common/ast_builder.c2 index 5b82a7e72..6cc6dd89d 100644 --- a/common/ast_builder.c2 +++ b/common/ast_builder.c2 @@ -37,10 +37,11 @@ public type Builder struct @(opaque) { Module* mod; // no ownership AST* ast; u32 ast_idx; - u32 c2_name; - u32 main_name; + u32 c2_name; // index into astPool + u32 main_name; // index into astPool bool is_interface; bool is_private; + BuiltinKind native_kind; Attr[8] attrs; u32 num_attrs; @@ -63,6 +64,7 @@ public fn Builder* create(Context* context, b.auxPool = auxPool; b.c2_name = c2_name; b.main_name = main_name; + b.native_kind = context.getWordSize() == 8 ? UInt64 : UInt32; b.attr_handler = attr_handler_; return b; @@ -95,6 +97,10 @@ public fn bool Builder.setExternal(Builder* b, bool is_interface) { return was_interface; } +public fn BuiltinKind Builder.getNativeKind(Builder* b) { + return b.native_kind; +} + public fn void Builder.actOnModule(Builder* b, u32 mod_name, SrcLoc mod_loc, diff --git a/compiler/compiler.c2 b/compiler/compiler.c2 index 7a90e2154..89fc36887 100644 --- a/compiler/compiler.c2 +++ b/compiler/compiler.c2 @@ -206,7 +206,6 @@ fn void Compiler.build(Compiler* c, diags.setWarningAsError(target.getWarnings().are_errors); c.diags.clear(); - c.context = ast_context.create(16*1024); c.astPool = string_pool.create(128*1024, 4096); // Note: keywords must be added first @@ -219,15 +218,6 @@ fn void Compiler.build(Compiler* c, c.parse_queue.init(false, 64); - c.attr_handler = attr_handler.create(diags, c.astPool, target.getWarnings()); - c.builder = ast_builder.create(c.context, - diags, - c.astPool, - c.auxPool, - c2_idx, - c.main_idx, - c.attr_handler); - c.allmodules.init(false, 128); c.components.init(); c.is_image = target.getKind() == Image; @@ -289,6 +279,21 @@ fn void Compiler.build(Compiler* c, #ifndef BOOTSTRAP c.addFeature("EXPERIMENTAL", "1"); #endif + + // TODO: reorganize these objects: + // ast.AstContext should the global object + c.context = ast_context.create(16*1024, c.targetInfo.intWidth / 8); + ast.initialize(c.context, c.astPool, color.useColor()); + + c.attr_handler = attr_handler.create(diags, c.astPool, target.getWarnings()); + c.builder = ast_builder.create(c.context, + diags, + c.astPool, + c.auxPool, + c2_idx, + c.main_idx, + c.attr_handler); + c.parser = c2_parser.create(sm, diags, c.astPool, @@ -297,8 +302,6 @@ fn void Compiler.build(Compiler* c, c.target.getFeatures(), c.target.hasAsserts()); - ast.initialize(c.context, c.astPool, c.targetInfo.intWidth / 8, color.useColor()); - c.analyser = module_analyser.create(c.diags, c.context, c.astPool, diff --git a/generator/c/c_generator.c2 b/generator/c/c_generator.c2 index 3e6bf8993..f207d7eac 100644 --- a/generator/c/c_generator.c2 +++ b/generator/c/c_generator.c2 @@ -1456,7 +1456,7 @@ fn void Generator.emit_external_header(Generator* gen, string_buffer.Buf* out) { out.add(Include_guard1); out.add(Warning_control); out.add(C_types); - if (ast.getWordSize() == 4) { + if (gen.targetInfo.intWidth == 32) { // ILP32 (32-bit int, long and pointers) out.add(```c typedef signed long long i64; diff --git a/generator/ir/ir_generator.c2 b/generator/ir/ir_generator.c2 index 992aa7e1b..299c0e3f7 100644 --- a/generator/ir/ir_generator.c2 +++ b/generator/ir/ir_generator.c2 @@ -224,6 +224,7 @@ fn ir.Type Generator.type2irtype(Generator* gen, QualType qt) { case Void: return None; case Pointer: + case Function: // TODO 32-bits return ir.Type.I64; case Array: @@ -247,9 +248,6 @@ fn ir.Type Generator.type2irtype(Generator* gen, QualType qt) { case Enum: EnumType* et = canon.getEnum(); return gen.type2irtype(et.getImplType()); - case Function: - // TODO 32-bits - return ir.Type.I64; case Alias: assert(0); break;