diff options
| author | Baitinq <[email protected]> | 2025-07-13 11:26:30 +0200 |
|---|---|---|
| committer | Baitinq <[email protected]> | 2025-07-13 11:26:30 +0200 |
| commit | 792f56587f1594c96c12c7a3446c9c245295a0a7 (patch) | |
| tree | ad527e244b5658f32449b51f5940f00cb239f8ad | |
| parent | Boostrap: Support assigning to ptrs (diff) | |
| download | pry-lang-792f56587f1594c96c12c7a3446c9c245295a0a7.tar.gz pry-lang-792f56587f1594c96c12c7a3446c9c245295a0a7.tar.bz2 pry-lang-792f56587f1594c96c12c7a3446c9c245295a0a7.zip | |
Boostrap: Support sizeof builtin
| -rw-r--r-- | src/bootstrap/codegen.pry | 27 | ||||
| -rw-r--r-- | src/bootstrap/llvm.pry | 5 | ||||
| -rw-r--r-- | src/bootstrap/parser.pry | 46 |
3 files changed, 77 insertions, 1 deletions
diff --git a/src/bootstrap/codegen.pry b/src/bootstrap/codegen.pry index 57f5472..be2ee5c 100644 --- a/src/bootstrap/codegen.pry +++ b/src/bootstrap/codegen.pry @@ -95,6 +95,7 @@ let codegen = struct { whil_block: LLVMBasicBlockRef, current_function: LLVMValueRef, current_function_retur_type: *Node, + llvm_target_data: LLVMTargetDataRef, }; let codegen_init = (alloc: *arena) => *codegen { @@ -111,6 +112,7 @@ let codegen_init = (alloc: *arena) => *codegen { let c = cast(*codegen, arena_alloc(alloc, sizeof(codegen))); (*c).llvm_module = module; + (*c).llvm_target_data = LLVMGetModuleDataLayout(module); (*c).llvm_context = context; (*c).builder = builder; (*c).arena = alloc; @@ -693,7 +695,6 @@ let codegen_generate_expression_value = (c: *codegen, expression: *Node, name: * v.stack_level = cast(*i64, null); v.node = expression; v.node_type = expression; - printf("RET\n"); return codegen_create_variable(c, v); }; @@ -713,6 +714,30 @@ let codegen_generate_expression_value = (c: *codegen, expression: *Node, name: * v.node_type = exp.typ; return codegen_create_variable(c, v); }; + + if ((*expression).type == NODE_SIZEOF_STATEMENT) { + let exp = *cast(*NODE_SIZEOF_STATEMENT_DATA, (*expression).data); + let typ = codegen_get_llvm_type(c, exp.typ); + assert(typ != cast(*LLVMTypeRef, null)); + let size_in_bytes = LLVMStoreSizeOfType((*c).llvm_target_data, *typ); + let size_val = LLVMConstInt(LLVMInt64Type(), size_in_bytes, 0); + + let node_type = Node{}; + node_type.type = NODE_TYPE_SIMPLE_TYPE; + + let d = cast(*NODE_TYPE_SIMPLE_TYPE_DATA, arena_alloc((*c).arena, sizeof(NODE_TYPE_SIMPLE_TYPE_DATA))); + (*d).name = "i64"; + (*d).underlying_type = cast(*Node, null); + node_type.data = cast(*void, d); + + let v = Variable{}; + v.value = size_val; + v.type = cast(LLVMTypeRef, null); + v.stack_level = cast(*i64, null); + v.node = expression; + v.node_type = create_node(c, node_type); + return codegen_create_variable(c, v); + }; printf("ASSERT 1: %d\n", (*expression).type); assert(false); diff --git a/src/bootstrap/llvm.pry b/src/bootstrap/llvm.pry index 3f794e3..1771908 100644 --- a/src/bootstrap/llvm.pry +++ b/src/bootstrap/llvm.pry @@ -252,6 +252,7 @@ let LLVMInitializeAllDisassemblers = () => void { let LLVMBuilderRef = newtype *void; let LLVMModuleRef = newtype *void; +let LLVMTargetDataRef = newtype *void; let LLVMTargetMachineRef = newtype *void; let LLVMContextRef = newtype *void; let LLVMTargetRef = newtype *void; @@ -262,6 +263,7 @@ let LLVMValueKind = newtype i64; let LLVMTypeRef = newtype *void; let LLVMBasicBlockRef = newtype *void; +extern LLVMGetModuleDataLayout = (LLVMModuleRef) => LLVMTargetDataRef; extern LLVMConstInt = (LLVMTypeRef, i64, i64) => LLVMValueRef; extern LLVMInt64Type = () => LLVMTypeRef; extern LLVMInt1Type = () => LLVMTypeRef; @@ -341,3 +343,6 @@ let LLVMIntSGT = 38; let LLVMIntSGE = 39; let LLVMIntSLT = 40; let LLVMIntSLE = 41; + +extern LLVMStoreSizeOfType = (LLVMTargetDataRef, LLVMTypeRef) => i64; + diff --git a/src/bootstrap/parser.pry b/src/bootstrap/parser.pry index 5c34edb..355b54d 100644 --- a/src/bootstrap/parser.pry +++ b/src/bootstrap/parser.pry @@ -345,6 +345,40 @@ let parser_parse_cast_statement = (p: *parser) => *Node { return create_node(p, r); }; +/* SizeOfStatement ::= "sizeof" LPAREN TYPE RPAREN */ +let parser_parse_sizeof_statement = (p: *parser) => *Node { + let ident = parser_accept_token(p, TOKEN_IDENTIFIER); + if ident == cast(*token, null) { + return cast(*Node, null); + }; + + if !strcmp(cast(*i8, (*ident).data), "sizeof") { + return cast(*Node, null); + }; + + if parser_accept_token(p, TOKEN_LPAREN) == cast(*token, null) { + return cast(*Node, null); + }; + + let typ = parser_parse_type(p); + if typ == cast(*Node, null) { + return cast(*Node, null); + }; + + if parser_accept_token(p, TOKEN_RPAREN) == cast(*token, null) { + return cast(*Node, null); + }; + + let d = cast(*NODE_SIZEOF_STATEMENT_DATA , arena_alloc((*p).arena, sizeof(NODE_SIZEOF_STATEMENT_DATA ))); + (*d).typ = typ; + + let r = Node{}; + r.type = NODE_SIZEOF_STATEMENT; + r.data = cast(*void, d); + + return create_node(p, r); +}; + /* FunctionType ::= LPAREN (Type ("," Type)*)? RPAREN ARROW Type */ let parser_parse_function_type = (p: *parser) => *Node { if parser_accept_token(p, TOKEN_LPAREN) == cast(*token, null) { @@ -824,6 +858,10 @@ let parser_parse_postfix_expression = (p: *parser) => *Node { if ex != cast(*Node, null) { return ex; }; + let ex = parser_accept_parse(p, parser_parse_sizeof_statement); + if ex != cast(*Node, null) { + return ex; + }; let ex = parser_accept_parse(p, parse_function_call_statement); if ex != cast(*Node, null) { return ex; @@ -1136,6 +1174,14 @@ let parser_parse_statement = (p: *parser) => *Node { }; return fn_call; }; + + let fn_call = parser_accept_parse(p, parser_parse_sizeof_statement); + if fn_call != cast(*Node, null) { + if parser_accept_token(p, TOKEN_SEMICOLON) == cast(*token, null) { + return cast(*Node, null); + }; + return fn_call; + }; let fn_call = parser_accept_parse(p, parse_function_call_statement); if fn_call != cast(*Node, null) { |