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) };
}
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) {
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;
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];
}
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.");
}
&& 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) {
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;
}
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;
}