Commit 3268276b58

Andrew Kelley <superjoe30@gmail.com>
2018-01-12 02:58:28
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
1 parent 465e75b
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;
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) {
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;
     }
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);
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) {
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);
+}