From 742a8f245d9e26e6a88f5e005bb5e905d979846f Mon Sep 17 00:00:00 2001 From: Brendan Hansen Date: Tue, 31 May 2022 07:41:51 -0500 Subject: [PATCH] added taking pointers to literals --- core/onyx/cptr.onyx | 8 +++++++- include/astnodes.h | 5 +++++ src/checker.c | 17 ++++++++++++++++- src/wasm_emit.c | 14 +++++++++++++- 4 files changed, 41 insertions(+), 3 deletions(-) diff --git a/core/onyx/cptr.onyx b/core/onyx/cptr.onyx index 5f6530a4..d8e91311 100644 --- a/core/onyx/cptr.onyx +++ b/core/onyx/cptr.onyx @@ -1,9 +1,11 @@ package core +#tag conv.Custom_Format.{ #solidify cptr.format {T=T} } cptr :: struct (T: type_expr) { data: u64; - make :: (ptr: ^$T) -> cptr(T) { + make :: macro (ptr: ^$T) -> cptr(T) { + __cptr_make :: __cptr_make return .{ __cptr_make(ptr) }; } @@ -36,6 +38,10 @@ cptr :: struct (T: type_expr) { assert(mem_base_ptr <= this.data + 1 && this.data + 1 <= mem_base_ptr + ~~(wasm.memory_size() << 16), "Invalid conversion from cptr to rawptr: pointer value out of Onyx memory range."); return ~~(this.data - mem_base_ptr + 1); } + + format :: (output: ^conv.Format_Output, format: ^conv.Format, p: ^cptr($T)) { + conv.format(output, "cptr({})[0x{b16}]", T, p.data); + } } #operator + macro (p: cptr($T), v: i32) -> cptr(T) { diff --git a/include/astnodes.h b/include/astnodes.h index 1ba0d254..0d4296fb 100644 --- a/include/astnodes.h +++ b/include/astnodes.h @@ -1742,6 +1742,11 @@ static inline b32 node_is_auto_cast(AstNode* node) { return (node->kind == Ast_Kind_Unary_Op) && (((AstUnaryOp *) node)->operation == Unary_Op_Auto_Cast); } +static inline b32 node_is_addressable_literal(AstNode* node) { + return (node->kind == Ast_Kind_Struct_Literal) + || (node->kind == Ast_Kind_Array_Literal); +} + static inline Type* get_expression_type(AstTyped* expr) { switch (expr->kind) { case Ast_Kind_Block: case Ast_Kind_If: case Ast_Kind_While: return NULL; diff --git a/src/checker.c b/src/checker.c index ef038ecd..ee31a9a8 100644 --- a/src/checker.c +++ b/src/checker.c @@ -149,6 +149,16 @@ CheckStatus check_return(AstReturn* retnode) { node_get_type_name(retnode->expr)); } + // + // Catch the obvious case of return '^.{ ... }', as that will never + // be legal. + if (retnode->expr->kind == Ast_Kind_Address_Of) { + AstAddressOf *aof = (AstAddressOf *) retnode->expr; + if (node_is_addressable_literal((AstNode *) aof->expr)) { + ERROR(retnode->token->pos, "Cannot return a pointer to a literal, as the space reserved for the literal will be freed upon returning."); + } + } + } else { if (*expected_return_type == &type_auto_return) { *expected_return_type = &basic_types[Basic_Kind_Void]; @@ -1482,6 +1492,10 @@ CheckStatus check_address_of(AstAddressOf** paof) { } CHECK(expression, &aof->expr); + if (node_is_addressable_literal((AstNode *) aof->expr)) { + resolve_expression_type(aof->expr); + } + if (aof->expr->type == NULL) { YIELD(aof->token->pos, "Trying to resolve type of expression to take a reference."); } @@ -1502,7 +1516,8 @@ CheckStatus check_address_of(AstAddressOf** paof) { && expr->kind != Ast_Kind_Field_Access && expr->kind != Ast_Kind_Memres && expr->kind != Ast_Kind_Local - && expr->kind != Ast_Kind_Constraint_Sentinel) + && expr->kind != Ast_Kind_Constraint_Sentinel + && !node_is_addressable_literal((AstNode *) expr)) || (expr->flags & Ast_Flag_Cannot_Take_Addr) != 0) { if (aof->can_be_removed) { diff --git a/src/wasm_emit.c b/src/wasm_emit.c index d97b811f..012f24f6 100644 --- a/src/wasm_emit.c +++ b/src/wasm_emit.c @@ -2618,7 +2618,9 @@ EMIT_FUNC(location_return_offset, AstTyped* expr, u64* offset_return) { switch (expr->kind) { case Ast_Kind_Param: - case Ast_Kind_Local: { + case Ast_Kind_Local: + case Ast_Kind_Array_Literal: + case Ast_Kind_Struct_Literal: { emit_local_location(mod, &code, (AstLocal *) expr, offset_return); break; } @@ -2817,6 +2819,16 @@ EMIT_FUNC(expression, AstTyped* expr) { case Ast_Kind_Address_Of: { AstAddressOf* aof = (AstAddressOf *) expr; + + if (node_is_addressable_literal((AstNode *) aof->expr)) { + aof->expr->flags |= Ast_Flag_Decl_Followed_By_Init; + aof->expr->flags |= Ast_Flag_Address_Taken; + emit_local_allocation(mod, &code, aof->expr); + emit_location(mod, &code, aof->expr); + emit_expression(mod, &code, aof->expr); + emit_store_instruction(mod, &code, aof->expr->type, 0); + } + emit_location(mod, &code, aof->expr); break; } -- 2.25.1