aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrew Kelley <superjoe30@gmail.com>2016-01-06 01:28:58 -0700
committerAndrew Kelley <superjoe30@gmail.com>2016-01-06 01:28:58 -0700
commit3c43bc9208701af151a0346744e3bfc7eae43042 (patch)
treeb3732004becc9b759ddad1a86813668059cfc8d9 /src
parent4ef062b9c819a2d7bfa9dd3394713ac9e8051660 (diff)
downloadzig-3c43bc9208701af151a0346744e3bfc7eae43042.tar.gz
zig-3c43bc9208701af151a0346744e3bfc7eae43042.zip
support unknown size arrays
Diffstat (limited to 'src')
-rw-r--r--src/analyze.cpp116
-rw-r--r--src/analyze.hpp6
-rw-r--r--src/codegen.cpp43
-rw-r--r--src/parser.cpp14
4 files changed, 108 insertions, 71 deletions
diff --git a/src/analyze.cpp b/src/analyze.cpp
index d4cea049a8..51f53fa800 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -219,7 +219,7 @@ static TypeTableEntry *get_array_type(CodeGen *g, ImportTableEntry *import,
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdArray);
entry->type_ref = LLVMArrayType(child_type->type_ref, array_size);
buf_resize(&entry->name, 0);
- buf_appendf(&entry->name, "[%s; %" PRIu64 "]", buf_ptr(&child_type->name), array_size);
+ buf_appendf(&entry->name, "[%" PRIu64 "]%s", array_size, buf_ptr(&child_type->name));
entry->size_in_bits = child_type->size_in_bits * array_size;
entry->align_in_bits = child_type->align_in_bits;
@@ -235,6 +235,55 @@ static TypeTableEntry *get_array_type(CodeGen *g, ImportTableEntry *import,
}
}
+static TypeTableEntry *get_unknown_size_array_type(CodeGen *g, ImportTableEntry *import,
+ TypeTableEntry *child_type, bool is_const)
+{
+ TypeTableEntry **parent_pointer = is_const ?
+ &child_type->unknown_size_array_const_parent :
+ &child_type->unknown_size_array_mut_parent;
+ if (*parent_pointer) {
+ return *parent_pointer;
+ } else {
+ TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdStruct);
+
+ buf_resize(&entry->name, 0);
+ buf_appendf(&entry->name, "[]%s", buf_ptr(&child_type->name));
+ entry->type_ref = LLVMStructCreateNamed(LLVMGetGlobalContext(), buf_ptr(&entry->name));
+
+ TypeTableEntry *pointer_type = get_pointer_to_type(g, child_type, is_const);
+
+ unsigned element_count = 2;
+ LLVMTypeRef element_types[] = {
+ pointer_type->type_ref,
+ g->builtin_types.entry_usize->type_ref,
+ };
+ LLVMStructSetBody(entry->type_ref, element_types, element_count, false);
+
+ entry->size_in_bits = g->pointer_size_bytes * 2 * 8;
+ entry->align_in_bits = g->pointer_size_bytes * 8;
+ entry->data.structure.is_packed = false;
+ entry->data.structure.is_unknown_size_array = true;
+ entry->data.structure.field_count = element_count;
+ entry->data.structure.fields = allocate<TypeStructField>(element_count);
+ entry->data.structure.fields[0].name = buf_create_from_str("ptr");
+ entry->data.structure.fields[0].type_entry = pointer_type;
+ entry->data.structure.fields[1].name = buf_create_from_str("len");
+ entry->data.structure.fields[1].type_entry = g->builtin_types.entry_usize;
+
+ LLVMZigDIType *di_element_types[] = {
+ pointer_type->di_type,
+ g->builtin_types.entry_usize->di_type,
+ };
+ LLVMZigDIScope *compile_unit_scope = LLVMZigCompileUnitToScope(g->compile_unit);
+ entry->di_type = LLVMZigCreateDebugStructType(g->dbuilder, compile_unit_scope,
+ buf_ptr(&entry->name), g->dummy_di_file, 0, entry->size_in_bits, entry->align_in_bits, 0,
+ nullptr, di_element_types, element_count, 0, nullptr, "");
+
+ *parent_pointer = entry;
+ return entry;
+ }
+}
+
static TypeTableEntry *eval_const_expr(CodeGen *g, BlockContext *context,
AstNode *node, AstNodeNumberLiteral *out_number_literal)
{
@@ -313,38 +362,47 @@ static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node, ImportTableEntry
}
case AstNodeTypeTypeArray:
{
- resolve_type(g, node->data.type.child_type, import, context);
- TypeTableEntry *child_type = node->data.type.child_type->codegen_node->data.type_node.entry;
+ TypeTableEntry *child_type = resolve_type(g, node->data.type.child_type, import, context);
if (child_type->id == TypeTableEntryIdUnreachable) {
add_node_error(g, node,
buf_create_from_str("array of unreachable not allowed"));
- }
-
- AstNode *size_node = node->data.type.array_size;
- TypeTableEntry *size_type = analyze_expression(g, import, context,
- g->builtin_types.entry_usize, size_node);
- if (size_type->id == TypeTableEntryIdInvalid) {
type_node->entry = g->builtin_types.entry_invalid;
return type_node->entry;
}
- AstNodeNumberLiteral number_literal;
- TypeTableEntry *resolved_type = eval_const_expr(g, context, size_node, &number_literal);
+ AstNode *size_node = node->data.type.array_size;
- if (resolved_type->id == TypeTableEntryIdInt) {
- if (resolved_type->data.integral.is_signed) {
- add_node_error(g, size_node,
- buf_create_from_str("array size must be unsigned integer"));
+ if (size_node) {
+ TypeTableEntry *size_type = analyze_expression(g, import, context,
+ g->builtin_types.entry_usize, size_node);
+ if (size_type->id == TypeTableEntryIdInvalid) {
type_node->entry = g->builtin_types.entry_invalid;
+ return type_node->entry;
+ }
+
+ AstNodeNumberLiteral number_literal;
+ TypeTableEntry *resolved_type = eval_const_expr(g, context, size_node, &number_literal);
+
+ if (resolved_type->id == TypeTableEntryIdInt) {
+ if (resolved_type->data.integral.is_signed) {
+ add_node_error(g, size_node,
+ buf_create_from_str("array size must be unsigned integer"));
+ type_node->entry = g->builtin_types.entry_invalid;
+ } else {
+ type_node->entry = get_array_type(g, import, child_type, number_literal.data.x_uint);
+ }
} else {
- type_node->entry = get_array_type(g, import, child_type, number_literal.data.x_uint);
+ add_node_error(g, size_node,
+ buf_create_from_str("unable to resolve constant expression"));
+ type_node->entry = g->builtin_types.entry_invalid;
}
+ return type_node->entry;
} else {
- add_node_error(g, size_node,
- buf_create_from_str("unable to resolve constant expression"));
- type_node->entry = g->builtin_types.entry_invalid;
+ type_node->entry = get_unknown_size_array_type(g, import, child_type,
+ node->data.type.is_const);
+ return type_node->entry;
}
- return type_node->entry;
+
}
case AstNodeTypeTypeMaybe:
{
@@ -1016,13 +1074,14 @@ static TypeTableEntry *resolve_type_compatibility(CodeGen *g, BlockContext *cont
return expected_type;
}
- // implicit constant sized array to string conversion
- if (expected_type == g->builtin_types.entry_string &&
+ // implicit constant sized array to unknown size array conversion
+ if (expected_type->id == TypeTableEntryIdStruct &&
+ expected_type->data.structure.is_unknown_size_array &&
actual_type->id == TypeTableEntryIdArray &&
- actual_type->data.array.child_type == g->builtin_types.entry_u8)
+ actual_type->data.array.child_type == expected_type->data.structure.fields[0].type_entry->data.pointer.child_type)
{
node->codegen_node->expr_node.implicit_cast.after_type = expected_type;
- node->codegen_node->expr_node.implicit_cast.op = CastOpArrayToString;
+ node->codegen_node->expr_node.implicit_cast.op = CastOpToUnknownSizeArray;
node->codegen_node->expr_node.implicit_cast.source_node = node;
context->cast_expr_alloca_list.append(&node->codegen_node->expr_node.implicit_cast);
return expected_type;
@@ -1292,11 +1351,12 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B
{
cast_node->op = CastOpIntWidenOrShorten;
return wanted_type;
- } else if (wanted_type == g->builtin_types.entry_string &&
- actual_type->id == TypeTableEntryIdArray &&
- actual_type->data.array.child_type == g->builtin_types.entry_u8)
+ } else if (wanted_type->id == TypeTableEntryIdStruct &&
+ wanted_type->data.structure.is_unknown_size_array &&
+ actual_type->id == TypeTableEntryIdArray &&
+ actual_type->data.array.child_type == wanted_type->data.structure.fields[0].type_entry)
{
- cast_node->op = CastOpArrayToString;
+ cast_node->op = CastOpToUnknownSizeArray;
context->cast_expr_alloca_list.append(cast_node);
return wanted_type;
} else if (actual_type->id == TypeTableEntryIdNumberLiteral &&
diff --git a/src/analyze.hpp b/src/analyze.hpp
index dcb85c94a1..8e3f569302 100644
--- a/src/analyze.hpp
+++ b/src/analyze.hpp
@@ -46,6 +46,7 @@ struct TypeTableEntryStruct {
TypeStructField *fields;
uint64_t size_bytes;
bool is_invalid; // true if any fields are invalid
+ bool is_unknown_size_array;
// reminder: hash tables must be initialized before use
HashMap<Buf *, FnTableEntry *, buf_hash, buf_eql_buf> fn_table;
@@ -100,6 +101,8 @@ struct TypeTableEntry {
TypeTableEntry *pointer_mut_parent;
HashMap<uint64_t, TypeTableEntry *, uint64_hash, uint64_eq> arrays_by_size;
TypeTableEntry *maybe_parent;
+ TypeTableEntry *unknown_size_array_const_parent;
+ TypeTableEntry *unknown_size_array_mut_parent;
};
@@ -175,7 +178,6 @@ struct CodeGen {
TypeTableEntry *entry_f32;
TypeTableEntry *entry_f64;
TypeTableEntry *entry_c_string_literal;
- TypeTableEntry *entry_string;
TypeTableEntry *entry_void;
TypeTableEntry *entry_unreachable;
TypeTableEntry *entry_invalid;
@@ -283,7 +285,7 @@ enum CastOp {
CastOpNothing,
CastOpPtrToInt,
CastOpIntWidenOrShorten,
- CastOpArrayToString,
+ CastOpToUnknownSizeArray,
CastOpMaybeWrap,
CastOpPointerReinterpret,
};
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 9c2cf3c88f..403261acc4 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -462,14 +462,17 @@ static LLVMValueRef gen_bare_cast(CodeGen *g, AstNode *node, LLVMValueRef expr_v
add_debug_source_node(g, node);
return LLVMBuildTrunc(g->builder, expr_val, wanted_type->type_ref, "");
}
- case CastOpArrayToString:
+ case CastOpToUnknownSizeArray:
{
assert(cast_node->ptr);
+ TypeTableEntry *pointer_type = wanted_type->data.structure.fields[0].type_entry;
+
add_debug_source_node(g, node);
LLVMValueRef ptr_ptr = LLVMBuildStructGEP(g->builder, cast_node->ptr, 0, "");
- LLVMBuildStore(g->builder, expr_val, ptr_ptr);
+ LLVMValueRef expr_bitcast = LLVMBuildBitCast(g->builder, expr_val, pointer_type->type_ref, "");
+ LLVMBuildStore(g->builder, expr_bitcast, ptr_ptr);
LLVMValueRef len_ptr = LLVMBuildStructGEP(g->builder, cast_node->ptr, 1, "");
LLVMValueRef len_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref,
@@ -1925,41 +1928,6 @@ static void define_builtin_types(CodeGen *g) {
entry->di_type = g->builtin_types.entry_void->di_type;
g->builtin_types.entry_unreachable = entry;
}
- {
- TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdStruct);
-
- TypeTableEntry *const_pointer_to_u8 = get_pointer_to_type(g, g->builtin_types.entry_u8, true);
-
- unsigned element_count = 2;
- LLVMTypeRef element_types[] = {
- const_pointer_to_u8->type_ref,
- g->builtin_types.entry_usize->type_ref
- };
- entry->type_ref = LLVMStructCreateNamed(LLVMGetGlobalContext(), "string");
- LLVMStructSetBody(entry->type_ref, element_types, element_count, false);
-
- buf_init_from_str(&entry->name, "string");
- entry->size_in_bits = g->pointer_size_bytes * 2 * 8;
- entry->align_in_bits = g->pointer_size_bytes;
- entry->data.structure.is_packed = false;
- entry->data.structure.field_count = element_count;
- entry->data.structure.fields = allocate<TypeStructField>(element_count);
- entry->data.structure.fields[0].name = buf_create_from_str("ptr");
- entry->data.structure.fields[0].type_entry = const_pointer_to_u8;
- entry->data.structure.fields[1].name = buf_create_from_str("len");
- entry->data.structure.fields[1].type_entry = g->builtin_types.entry_usize;
-
- LLVMZigDIType *di_element_types[] = {
- const_pointer_to_u8->di_type,
- g->builtin_types.entry_usize->di_type
- };
- LLVMZigDIScope *compile_unit_scope = LLVMZigCompileUnitToScope(g->compile_unit);
- entry->di_type = LLVMZigCreateDebugStructType(g->dbuilder, compile_unit_scope,
- "string", g->dummy_di_file, 0, entry->size_in_bits, entry->align_in_bits, 0,
- nullptr, di_element_types, element_count, 0, nullptr, "");
-
- g->builtin_types.entry_string = entry;
- }
}
@@ -2103,7 +2071,6 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *abs_full_path,
import_entry->type_table.put(&g->builtin_types.entry_f64->name, g->builtin_types.entry_f64);
import_entry->type_table.put(&g->builtin_types.entry_void->name, g->builtin_types.entry_void);
import_entry->type_table.put(&g->builtin_types.entry_unreachable->name, g->builtin_types.entry_unreachable);
- import_entry->type_table.put(&g->builtin_types.entry_string->name, g->builtin_types.entry_string);
import_entry->root = ast_parse(source_code, tokenization.tokens, import_entry, g->err_color);
assert(import_entry->root);
diff --git a/src/parser.cpp b/src/parser.cpp
index 36038a3bc2..24daca8864 100644
--- a/src/parser.cpp
+++ b/src/parser.cpp
@@ -219,7 +219,7 @@ void ast_print(AstNode *node, int indent) {
}
case AstNodeTypeTypePointer:
{
- const char *const_or_mut_str = node->data.type.is_const ? "const" : "mut";
+ const char *const_or_mut_str = node->data.type.is_const ? "const" : "var";
fprintf(stderr, "'%s' PointerType\n", const_or_mut_str);
ast_print(node->data.type.child_type, indent + 2);
@@ -227,9 +227,11 @@ void ast_print(AstNode *node, int indent) {
}
case AstNodeTypeTypeArray:
{
- fprintf(stderr, "ArrayType\n");
+ const char *const_or_mut_str = node->data.type.is_const ? "const" : "var";
+ fprintf(stderr, "'%s' ArrayType\n", const_or_mut_str);
+ if (node->data.type.array_size)
+ ast_print(node->data.type.array_size, indent + 2);
ast_print(node->data.type.child_type, indent + 2);
- ast_print(node->data.type.array_size, indent + 2);
break;
}
case AstNodeTypeTypeMaybe:
@@ -1107,6 +1109,12 @@ static AstNode *ast_parse_type(ParseContext *pc, int *token_index) {
ast_eat_token(pc, token_index, TokenIdRBracket);
+ Token *const_tok = &pc->tokens->at(*token_index);
+ if (const_tok->id == TokenIdKeywordConst) {
+ *token_index += 1;
+ node->data.type.is_const = true;
+ }
+
node->data.type.child_type = ast_parse_type(pc, token_index);
} else {
ast_invalid_token_error(pc, token);