zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit 3268276b58d8b65cb295b738d7c14174005bd84e (tree)
parent 465e75bc5a41aa899b673c0a3ff59d6da871fbe6
Author: Andrew Kelley <superjoe30@gmail.com>
Date:   Thu, 11 Jan 2018 20:58:28 -0500

the same string literal codegens to the same constant

this makes it so that you can send the same string literal
as a comptime slice and get the same type

Diffstat:
Msrc/all_types.hpp | 1+
Msrc/analyze.cpp | 8++++++++
Msrc/buffer.cpp | 5++++-
Msrc/codegen.cpp | 1+
Msrc/ir.cpp | 8++++----
Mtest/cases/eval.zig | 13+++++++++++++
6 files changed, 31 insertions(+), 5 deletions(-)

diff --git a/src/all_types.hpp b/src/all_types.hpp @@ -1421,6 +1421,7 @@ struct CodeGen { HashMap<ZigLLVMFnKey, LLVMValueRef, zig_llvm_fn_key_hash, zig_llvm_fn_key_eql> llvm_fn_table; HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> exported_symbol_names; HashMap<Buf *, Tld *, buf_hash, buf_eql_buf> external_prototypes; + HashMap<Buf *, ConstExprValue *, buf_hash, buf_eql_buf> string_literals_table; ZigList<ImportTableEntry *> import_queue; diff --git a/src/analyze.cpp b/src/analyze.cpp @@ -4370,6 +4370,12 @@ bool type_requires_comptime(TypeTableEntry *type_entry) { } void init_const_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str) { + auto entry = g->string_literals_table.maybe_get(str); + if (entry != nullptr) { + *const_val = *entry->value; + return; + } + const_val->special = ConstValSpecialStatic; const_val->type = get_array_type(g, g->builtin_types.entry_u8, buf_len(str)); const_val->data.x_array.s_none.elements = create_const_vals(buf_len(str)); @@ -4380,6 +4386,8 @@ void init_const_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str) { this_char->type = g->builtin_types.entry_u8; bigint_init_unsigned(&this_char->data.x_bigint, (uint8_t)buf_ptr(str)[i]); } + + g->string_literals_table.put(str, const_val); } ConstExprValue *create_const_str_lit(CodeGen *g, Buf *str) { diff --git a/src/buffer.cpp b/src/buffer.cpp @@ -67,9 +67,12 @@ bool buf_eql_buf(Buf *buf, Buf *other) { uint32_t buf_hash(Buf *buf) { assert(buf->list.length); + size_t interval = buf->list.length / 256; + if (interval == 0) + interval = 1; // FNV 32-bit hash uint32_t h = 2166136261; - for (size_t i = 0; i < buf_len(buf); i += 1) { + for (size_t i = 0; i < buf_len(buf); i += interval) { h = h ^ ((uint8_t)buf->list.at(i)); h = h * 16777619; } diff --git a/src/codegen.cpp b/src/codegen.cpp @@ -87,6 +87,7 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out g->memoized_fn_eval_table.init(16); g->exported_symbol_names.init(8); g->external_prototypes.init(8); + g->string_literals_table.init(16); g->is_test_build = false; g->want_h_file = (out_type == OutTypeObj || out_type == OutTypeLib); buf_resize(&g->global_asm, 0); diff --git a/src/ir.cpp b/src/ir.cpp @@ -13224,9 +13224,9 @@ static TypeTableEntry *ir_analyze_instruction_embed_file(IrAnalyze *ira, IrInstr os_path_resolve(&source_dir_path, rel_file_path, &file_path); // load from file system into const expr - Buf file_contents = BUF_INIT; + Buf *file_contents = buf_alloc(); int err; - if ((err = os_fetch_file_path(&file_path, &file_contents))) { + if ((err = os_fetch_file_path(&file_path, file_contents))) { if (err == ErrorFileNotFound) { ir_add_error(ira, instruction->name, buf_sprintf("unable to find '%s'", buf_ptr(&file_path))); return ira->codegen->builtin_types.entry_invalid; @@ -13240,9 +13240,9 @@ static TypeTableEntry *ir_analyze_instruction_embed_file(IrAnalyze *ira, IrInstr // we'll have to invalidate the cache ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); - init_const_str_lit(ira->codegen, out_val, &file_contents); + init_const_str_lit(ira->codegen, out_val, file_contents); - return get_array_type(ira->codegen, ira->codegen->builtin_types.entry_u8, buf_len(&file_contents)); + return get_array_type(ira->codegen, ira->codegen->builtin_types.entry_u8, buf_len(file_contents)); } static TypeTableEntry *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstructionCmpxchg *instruction) { diff --git a/test/cases/eval.zig b/test/cases/eval.zig @@ -375,3 +375,16 @@ test "f128 at compile time is lossy" { // TODO need a better implementation of bigfloat_init_bigint // assert(f128(1 << 113) == 10384593717069655257060992658440192); + +pub fn TypeWithCompTimeSlice(comptime field_name: []const u8) -> type { + return struct { + pub const Node = struct { }; + }; +} + +test "string literal used as comptime slice is memoized" { + const a = "link"; + const b = "link"; + comptime assert(TypeWithCompTimeSlice(a).Node == TypeWithCompTimeSlice(b).Node); + comptime assert(TypeWithCompTimeSlice("link").Node == TypeWithCompTimeSlice("link").Node); +}