mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 06:13:07 +00:00
string literals have type *const u8
This commit is contained in:
parent
ab327344b6
commit
c6a9ab107b
@ -2,7 +2,7 @@ export executable "hello";
|
||||
|
||||
#link("c")
|
||||
extern {
|
||||
fn puts(s: *mut u8) -> i32;
|
||||
fn puts(s: *const u8) -> i32;
|
||||
fn exit(code: i32) -> unreachable;
|
||||
}
|
||||
|
||||
|
||||
@ -54,6 +54,26 @@ static void set_root_export_version(CodeGen *g, Buf *version_buf, AstNode *node)
|
||||
}
|
||||
}
|
||||
|
||||
TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const) {
|
||||
TypeTableEntry **parent_pointer = is_const ?
|
||||
&child_type->pointer_const_parent :
|
||||
&child_type->pointer_mut_parent;
|
||||
const char *const_or_mut_str = is_const ? "const" : "mut";
|
||||
if (*parent_pointer) {
|
||||
return *parent_pointer;
|
||||
} else {
|
||||
TypeTableEntry *entry = allocate<TypeTableEntry>(1);
|
||||
entry->type_ref = LLVMPointerType(child_type->type_ref, 0);
|
||||
buf_resize(&entry->name, 0);
|
||||
buf_appendf(&entry->name, "*%s %s", const_or_mut_str, buf_ptr(&child_type->name));
|
||||
entry->di_type = LLVMZigCreateDebugPointerType(g->dbuilder, child_type->di_type,
|
||||
g->pointer_size_bytes * 8, g->pointer_size_bytes * 8, buf_ptr(&entry->name));
|
||||
g->type_table.put(&entry->name, entry);
|
||||
*parent_pointer = entry;
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
|
||||
static void resolve_type(CodeGen *g, AstNode *node) {
|
||||
assert(!node->codegen_node);
|
||||
node->codegen_node = allocate<CodeGenNode>(1);
|
||||
@ -75,28 +95,12 @@ static void resolve_type(CodeGen *g, AstNode *node) {
|
||||
case AstNodeTypeTypePointer:
|
||||
{
|
||||
resolve_type(g, node->data.type.child_type);
|
||||
TypeNode *child_type_node = &node->data.type.child_type->codegen_node->data.type_node;
|
||||
if (child_type_node->entry == g->builtin_types.entry_unreachable) {
|
||||
TypeTableEntry *child_type = node->data.type.child_type->codegen_node->data.type_node.entry;
|
||||
if (child_type == g->builtin_types.entry_unreachable) {
|
||||
add_node_error(g, node,
|
||||
buf_create_from_str("pointer to unreachable not allowed"));
|
||||
}
|
||||
TypeTableEntry **parent_pointer = node->data.type.is_const ?
|
||||
&child_type_node->entry->pointer_const_parent :
|
||||
&child_type_node->entry->pointer_mut_parent;
|
||||
const char *const_or_mut_str = node->data.type.is_const ? "const" : "mut";
|
||||
if (*parent_pointer) {
|
||||
type_node->entry = *parent_pointer;
|
||||
} else {
|
||||
TypeTableEntry *entry = allocate<TypeTableEntry>(1);
|
||||
entry->type_ref = LLVMPointerType(child_type_node->entry->type_ref, 0);
|
||||
buf_resize(&entry->name, 0);
|
||||
buf_appendf(&entry->name, "*%s %s", const_or_mut_str, buf_ptr(&child_type_node->entry->name));
|
||||
entry->di_type = LLVMZigCreateDebugPointerType(g->dbuilder, child_type_node->entry->di_type,
|
||||
g->pointer_size_bytes * 8, g->pointer_size_bytes * 8, buf_ptr(&entry->name));
|
||||
g->type_table.put(&entry->name, entry);
|
||||
type_node->entry = entry;
|
||||
*parent_pointer = entry;
|
||||
}
|
||||
type_node->entry = get_pointer_to_type(g, child_type, node->data.type.is_const);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -284,23 +288,26 @@ static TypeTableEntry * get_return_type(BlockContext *context) {
|
||||
}
|
||||
|
||||
static void check_type_compatibility(CodeGen *g, AstNode *node, TypeTableEntry *expected_type, TypeTableEntry *actual_type) {
|
||||
if (expected_type == nullptr)
|
||||
return; // anything will do
|
||||
if (expected_type == actual_type)
|
||||
return; // good
|
||||
return; // match
|
||||
if (expected_type == g->builtin_types.entry_invalid || actual_type == g->builtin_types.entry_invalid)
|
||||
return; // already complained
|
||||
if (actual_type == g->builtin_types.entry_unreachable)
|
||||
return; // TODO: is this true?
|
||||
|
||||
// TODO better error message
|
||||
add_node_error(g, node, buf_sprintf("type mismatch."));
|
||||
add_node_error(g, node, buf_sprintf("type mismatch. expected %s. got %s", buf_ptr(&expected_type->name), buf_ptr(&actual_type->name)));
|
||||
}
|
||||
|
||||
static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context, TypeTableEntry *expected_type, AstNode *node) {
|
||||
TypeTableEntry *return_type = nullptr;
|
||||
switch (node->type) {
|
||||
case NodeTypeBlock:
|
||||
{
|
||||
// TODO: nested block scopes
|
||||
TypeTableEntry *return_type = g->builtin_types.entry_void;
|
||||
return_type = g->builtin_types.entry_void;
|
||||
for (int i = 0; i < node->data.block.statements.length; i += 1) {
|
||||
AstNode *child = node->data.block.statements.at(i);
|
||||
if (return_type == g->builtin_types.entry_unreachable) {
|
||||
@ -310,7 +317,7 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
|
||||
}
|
||||
return_type = analyze_expression(g, import, context, nullptr, child);
|
||||
}
|
||||
return return_type;
|
||||
break;
|
||||
}
|
||||
|
||||
case NodeTypeReturnExpr:
|
||||
@ -330,7 +337,8 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
|
||||
}
|
||||
|
||||
check_type_compatibility(g, node, expected_return_type, actual_return_type);
|
||||
return g->builtin_types.entry_unreachable;
|
||||
return_type = g->builtin_types.entry_unreachable;
|
||||
break;
|
||||
}
|
||||
|
||||
case NodeTypeBinOpExpr:
|
||||
@ -338,7 +346,8 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
|
||||
// TODO: think about expected types
|
||||
analyze_expression(g, import, context, expected_type, node->data.bin_op_expr.op1);
|
||||
analyze_expression(g, import, context, expected_type, node->data.bin_op_expr.op2);
|
||||
return expected_type;
|
||||
return_type = expected_type;
|
||||
break;
|
||||
}
|
||||
|
||||
case NodeTypeFnCallExpr:
|
||||
@ -358,7 +367,7 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
|
||||
analyze_expression(g, import, context, nullptr, child);
|
||||
}
|
||||
|
||||
return g->builtin_types.entry_invalid;
|
||||
return_type = g->builtin_types.entry_invalid;
|
||||
} else {
|
||||
FnTableEntry *fn_table_entry = entry->value;
|
||||
assert(fn_table_entry->proto_node->type == NodeTypeFnProto);
|
||||
@ -388,21 +397,23 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
|
||||
analyze_expression(g, import, context, expected_param_type, child);
|
||||
}
|
||||
|
||||
TypeTableEntry *return_type = fn_proto->return_type->codegen_node->data.type_node.entry;
|
||||
check_type_compatibility(g, node, expected_type, return_type);
|
||||
return return_type;
|
||||
return_type = fn_proto->return_type->codegen_node->data.type_node.entry;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case NodeTypeNumberLiteral:
|
||||
// TODO: generic literal int type
|
||||
return g->builtin_types.entry_i32;
|
||||
return_type = g->builtin_types.entry_i32;
|
||||
break;
|
||||
|
||||
case NodeTypeStringLiteral:
|
||||
zig_panic("TODO: string literal");
|
||||
return_type = g->builtin_types.entry_string_literal;
|
||||
break;
|
||||
|
||||
case NodeTypeUnreachable:
|
||||
return g->builtin_types.entry_unreachable;
|
||||
return_type = g->builtin_types.entry_unreachable;
|
||||
break;
|
||||
|
||||
case NodeTypeSymbol:
|
||||
// look up symbol in symbol table
|
||||
@ -423,7 +434,9 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
|
||||
case NodeTypeUse:
|
||||
zig_unreachable();
|
||||
}
|
||||
zig_unreachable();
|
||||
assert(return_type);
|
||||
check_type_compatibility(g, node, expected_type, return_type);
|
||||
return return_type;
|
||||
}
|
||||
|
||||
static void check_fn_def_control_flow(CodeGen *g, AstNode *node) {
|
||||
|
||||
@ -12,7 +12,10 @@ struct CodeGen;
|
||||
struct AstNode;
|
||||
struct Buf;
|
||||
|
||||
struct TypeTableEntry;
|
||||
|
||||
void semantic_analyze(CodeGen *g);
|
||||
void add_node_error(CodeGen *g, AstNode *node, Buf *msg);
|
||||
TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const);
|
||||
|
||||
#endif
|
||||
|
||||
@ -589,6 +589,7 @@ static void define_primitive_types(CodeGen *g) {
|
||||
g->type_table.put(&entry->name, entry);
|
||||
g->builtin_types.entry_u8 = entry;
|
||||
}
|
||||
g->builtin_types.entry_string_literal = get_pointer_to_type(g, g->builtin_types.entry_u8, true);
|
||||
{
|
||||
TypeTableEntry *entry = allocate<TypeTableEntry>(1);
|
||||
entry->type_ref = LLVMInt32Type();
|
||||
|
||||
@ -65,6 +65,7 @@ struct CodeGen {
|
||||
struct {
|
||||
TypeTableEntry *entry_u8;
|
||||
TypeTableEntry *entry_i32;
|
||||
TypeTableEntry *entry_string_literal;
|
||||
TypeTableEntry *entry_void;
|
||||
TypeTableEntry *entry_unreachable;
|
||||
TypeTableEntry *entry_invalid;
|
||||
|
||||
@ -99,7 +99,7 @@ static void add_compiling_test_cases(void) {
|
||||
add_simple_case("hello world with libc", R"SOURCE(
|
||||
#link("c")
|
||||
extern {
|
||||
fn puts(s: *mut u8) -> i32;
|
||||
fn puts(s: *const u8) -> i32;
|
||||
fn exit(code: i32) -> unreachable;
|
||||
}
|
||||
|
||||
@ -112,7 +112,7 @@ static void add_compiling_test_cases(void) {
|
||||
add_simple_case("function call", R"SOURCE(
|
||||
#link("c")
|
||||
extern {
|
||||
fn puts(s: *mut u8) -> i32;
|
||||
fn puts(s: *const u8) -> i32;
|
||||
fn exit(code: i32) -> unreachable;
|
||||
}
|
||||
|
||||
@ -134,7 +134,7 @@ static void add_compiling_test_cases(void) {
|
||||
add_simple_case("comments", R"SOURCE(
|
||||
#link("c")
|
||||
extern {
|
||||
fn puts(s: *mut u8) -> i32;
|
||||
fn puts(s: *const u8) -> i32;
|
||||
fn exit(code: i32) -> unreachable;
|
||||
}
|
||||
|
||||
@ -169,7 +169,7 @@ static void add_compiling_test_cases(void) {
|
||||
add_source_file(tc, "libc.zig", R"SOURCE(
|
||||
#link("c")
|
||||
extern {
|
||||
pub fn puts(s: *mut u8) -> i32;
|
||||
pub fn puts(s: *const u8) -> i32;
|
||||
pub fn exit(code: i32) -> unreachable;
|
||||
}
|
||||
)SOURCE");
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user