added taking pointers to literals
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Tue, 31 May 2022 12:41:51 +0000 (07:41 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Tue, 31 May 2022 12:41:51 +0000 (07:41 -0500)
core/onyx/cptr.onyx
include/astnodes.h
src/checker.c
src/wasm_emit.c

index 5f6530a43df628e7256f1fa16555e66f99075eea..d8e913116d591313012587e1b939480eb010bee7 100644 (file)
@@ -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) {
index 1ba0d254f6256d52896afa276b02c0e00ccd454f..0d4296fbe4f52fa95823d6a3727d8b06ae92f7b9 100644 (file)
@@ -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;
index ef038ecdae34a0b94ceb63ff0cd21aab7d870f22..ee31a9a86ecefc95c960433be8c0a19e2b04aec5 100644 (file)
@@ -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) {
index d97b811f47090d1647f16806014037610b879e91..012f24f6305da8c0a7746ee79b9bdf7875ccb7a0 100644 (file)
@@ -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;
         }