diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/codegen.zig | 23 | ||||
| -rw-r--r-- | src/parser.zig | 35 |
2 files changed, 55 insertions, 3 deletions
diff --git a/src/codegen.zig b/src/codegen.zig index b72e9c4..d246853 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -17,6 +17,7 @@ pub const CodeGenError = error{ pub const CodeGen = struct { llvm_module: llvm.LLVMModuleRef, + llvm_target_data: llvm.LLVMTargetDataRef, llvm_context: llvm.LLVMContextRef, builder: llvm.LLVMBuilderRef, environment: *Environment, @@ -43,6 +44,7 @@ pub const CodeGen = struct { const self = try arena.create(CodeGen); self.* = .{ .llvm_module = module, + .llvm_target_data = llvm.LLVMGetModuleDataLayout(module), .llvm_context = context, .builder = builder, .environment = try Environment.init(arena), @@ -753,6 +755,27 @@ pub const CodeGen = struct { .node_type = exp.typ, }); }, + .SIZEOF_STATEMENT => |exp| { + const typ = try self.get_llvm_type(exp.typ); + const size_in_bits = llvm.LLVMSizeOfTypeInBits(self.llvm_target_data, typ); + const size_in_bytes = size_in_bits / 8; + + const size_val = llvm.LLVMConstInt(llvm.LLVMInt64Type(), size_in_bytes, 0); + + return try self.create_variable(.{ + .value = size_val, + .type = null, + .node_type = try self.create_node(.{ + .TYPE = .{ + .SIMPLE_TYPE = .{ + .name = "i64", + }, + }, + }), + .stack_level = null, + .node = expression, + }); + }, .FIELD_ACCESS => |exp| { const ptr = self.environment.get_variable(exp.expression.PRIMARY_EXPRESSION.IDENTIFIER.name).?; diff --git a/src/parser.zig b/src/parser.zig index 95b4bf2..5db8fa8 100644 --- a/src/parser.zig +++ b/src/parser.zig @@ -111,6 +111,9 @@ pub const Node = union(enum) { typ: *Node, expression: *Node, }, + SIZEOF_STATEMENT: struct { + typ: *Node, + }, BREAK_STATEMENT: void, CONTINUE_STATEMENT: void, }; @@ -168,12 +171,13 @@ pub const Parser = struct { } }); } - // Statement ::= (AssignmentStatement | ImportDeclaration | ExternDeclaration | CastStatement | FunctionCallStatement | IfStatement | WhileStatement | ReturnStatement | "break" | "continue") SEMICOLON + // Statement ::= (AssignmentStatement | ImportDeclaration | ExternDeclaration | CastStatement | SizeOfStatement | FunctionCallStatement | IfStatement | WhileStatement | ReturnStatement | "break" | "continue") SEMICOLON fn parse_statement(self: *Parser) ParserError!*Node { errdefer if (!self.try_context) std.debug.print("Error parsing statement {any}\n", .{self.peek_token()}); const statement = - self.accept_parse(parse_cast_statement) orelse + self.accept_parse(parse_cast_statement) orelse //TODO: Can we not deal with cast / sizeof in parser? + self.accept_parse(parse_sizeof_statement) orelse self.accept_parse(parse_function_call_statement) orelse self.accept_parse(parse_if_statement) orelse self.accept_parse(parse_while_statement) orelse @@ -567,12 +571,14 @@ pub const Parser = struct { } }); } - // PostfixExpression ::= PrimaryExpression (FunctionCallStatement | FieldAccess )* + // PostfixExpression ::= PrimaryExpression (CastStatement | SizeOfStatement | FunctionCallStatement | FieldAccess )* fn parse_postfix_expression(self: *Parser) ParserError!*Node { errdefer if (!self.try_context) std.debug.print("Error parsing postfix expression {any}\n", .{self.peek_token()}); if (self.accept_parse(parse_cast_statement)) |stmt| { return stmt; + } else if (self.accept_parse(parse_sizeof_statement)) |stmt| { + return stmt; } else if (self.accept_parse(parse_function_call_statement)) |stmt| { return stmt; } else if (self.accept_parse(parse_field_access)) |stmt| { @@ -814,6 +820,29 @@ pub const Parser = struct { }); } + // SizeOfStatement ::= "sizeof" LPAREN TYPE RPAREN + fn parse_sizeof_statement(self: *Parser) ParserError!*Node { + errdefer if (!self.try_context) std.debug.print("Error parsing sizeof statement {any}\n", .{self.peek_token()}); + + const ident = try self.parse_token(tokenizer.TokenType.IDENTIFIER); + + if (!std.mem.eql(u8, "sizeof", ident.type.IDENTIFIER)) { + return ParserError.ParsingError; + } + + _ = try self.parse_token(tokenizer.TokenType.LPAREN); + + const typ = try self.parse_type(); + + _ = try self.parse_token(tokenizer.TokenType.RPAREN); + + return self.create_node(.{ + .SIZEOF_STATEMENT = .{ + .typ = typ, + }, + }); + } + // Type ::= IDENTIFIER | FunctionType fn parse_type(self: *Parser) ParserError!*Node { errdefer if (!self.try_context) std.debug.print("Error parsing type annotation {any}\n", .{self.peek_token()}); |