Skip to content

Commit

Permalink
the same string literal codegens to the same constant
Browse files Browse the repository at this point in the history
this makes it so that you can send the same string literal
as a comptime slice and get the same type
  • Loading branch information
andrewrk committed Jan 12, 2018
1 parent 465e75b commit 3268276
Show file tree
Hide file tree
Showing 6 changed files with 31 additions and 5 deletions.
1 change: 1 addition & 0 deletions src/all_types.hpp
Expand Up @@ -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;
Expand Down
8 changes: 8 additions & 0 deletions src/analyze.cpp
Expand Up @@ -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));
Expand All @@ -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) {
Expand Down
5 changes: 4 additions & 1 deletion src/buffer.cpp
Expand Up @@ -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;
}
Expand Down
1 change: 1 addition & 0 deletions src/codegen.cpp
Expand Up @@ -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);
Expand Down
8 changes: 4 additions & 4 deletions src/ir.cpp
Expand Up @@ -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;
Expand All @@ -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) {
Expand Down
13 changes: 13 additions & 0 deletions test/cases/eval.zig
Expand Up @@ -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);
}

0 comments on commit 3268276

Please sign in to comment.