Skip to content

Commit

Permalink
better string literal caching implementation
Browse files Browse the repository at this point in the history
We were caching the ConstExprValue of string literals,
which works if you can never modify ConstExprValues.
This premise is broken with `comptime var ...`.

So I implemented an optimization in ConstExprValue
arrays, where it stores a `Buf *` directly rather
than an array of ConstExprValues for the elements,
and then similar to array of undefined, it is
expanded into the canonical form when necessary.
However many operations can happen directly on the
`Buf *`, which is faster.

Furthermore, before a ConstExprValue array is expanded
into canonical form, it removes itself from the string
literal cache. This fixes the issue, because before an
array element is modified it would have to be expanded.

closes #1076
  • Loading branch information
andrewrk committed Sep 20, 2018
1 parent 4928217 commit f8fe517
Show file tree
Hide file tree
Showing 8 changed files with 278 additions and 210 deletions.
17 changes: 12 additions & 5 deletions src/all_types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,14 +130,18 @@ struct ConstUnionValue {
enum ConstArraySpecial {
ConstArraySpecialNone,
ConstArraySpecialUndef,
ConstArraySpecialBuf,
};

struct ConstArrayValue {
ConstArraySpecial special;
struct {
ConstExprValue *elements;
ConstParent parent;
} s_none;
union {
struct {
ConstExprValue *elements;
ConstParent parent;
} s_none;
Buf *s_buf;
} data;
};

enum ConstPtrSpecial {
Expand Down Expand Up @@ -983,6 +987,7 @@ struct FnTypeParamInfo {
};

struct GenericFnTypeId {
CodeGen *codegen;
ZigFn *fn_entry;
ConstExprValue *params;
size_t param_count;
Expand Down Expand Up @@ -1291,6 +1296,7 @@ struct FnExport {
};

struct ZigFn {
CodeGen *codegen;
LLVMValueRef llvm_value;
const char *llvm_name;
AstNode *proto_node;
Expand Down Expand Up @@ -1848,13 +1854,14 @@ enum ScopeId {
};

struct Scope {
ScopeId id;
CodeGen *codegen;
AstNode *source_node;

// if the scope has a parent, this is it
Scope *parent;

ZigLLVMDIScope *di_scope;
ScopeId id;
};

// This scope comes from global declarations or from
Expand Down
239 changes: 135 additions & 104 deletions src/analyze.cpp

Large diffs are not rendered by default.

30 changes: 15 additions & 15 deletions src/analyze.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,34 +84,34 @@ void init_tld(Tld *tld, TldId id, Buf *name, VisibMod visib_mod, AstNode *source
ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf *name,
bool is_const, ConstExprValue *init_value, Tld *src_tld);
ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node);
ZigFn *create_fn(AstNode *proto_node);
ZigFn *create_fn_raw(FnInline inline_value, GlobalLinkageId linkage);
ZigFn *create_fn(CodeGen *g, AstNode *proto_node);
ZigFn *create_fn_raw(CodeGen *g, FnInline inline_value);
void init_fn_type_id(FnTypeId *fn_type_id, AstNode *proto_node, size_t param_count_alloc);
AstNode *get_param_decl_node(ZigFn *fn_entry, size_t index);
bool type_requires_comptime(ZigType *type_entry);
Error ATTRIBUTE_MUST_USE ensure_complete_type(CodeGen *g, ZigType *type_entry);
Error ATTRIBUTE_MUST_USE type_resolve(CodeGen *g, ZigType *type_entry, ResolveStatus status);
void complete_enum(CodeGen *g, ZigType *enum_type);
bool ir_get_var_is_comptime(ZigVar *var);
bool const_values_equal(ConstExprValue *a, ConstExprValue *b);
bool const_values_equal(CodeGen *g, ConstExprValue *a, ConstExprValue *b);
void eval_min_max_value(CodeGen *g, ZigType *type_entry, ConstExprValue *const_val, bool is_max);
void eval_min_max_value_int(CodeGen *g, ZigType *int_type, BigInt *bigint, bool is_max);

void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val);
void analyze_fn_ir(CodeGen *g, ZigFn *fn_table_entry, AstNode *return_type_node);

ScopeBlock *create_block_scope(AstNode *node, Scope *parent);
ScopeDefer *create_defer_scope(AstNode *node, Scope *parent);
ScopeDeferExpr *create_defer_expr_scope(AstNode *node, Scope *parent);
Scope *create_var_scope(AstNode *node, Scope *parent, ZigVar *var);
ScopeCImport *create_cimport_scope(AstNode *node, Scope *parent);
ScopeLoop *create_loop_scope(AstNode *node, Scope *parent);
ScopeSuspend *create_suspend_scope(AstNode *node, Scope *parent);
ScopeFnDef *create_fndef_scope(AstNode *node, Scope *parent, ZigFn *fn_entry);
ScopeDecls *create_decls_scope(AstNode *node, Scope *parent, ZigType *container_type, ImportTableEntry *import);
Scope *create_comptime_scope(AstNode *node, Scope *parent);
Scope *create_coro_prelude_scope(AstNode *node, Scope *parent);
Scope *create_runtime_scope(AstNode *node, Scope *parent, IrInstruction *is_comptime);
ScopeBlock *create_block_scope(CodeGen *g, AstNode *node, Scope *parent);
ScopeDefer *create_defer_scope(CodeGen *g, AstNode *node, Scope *parent);
ScopeDeferExpr *create_defer_expr_scope(CodeGen *g, AstNode *node, Scope *parent);
Scope *create_var_scope(CodeGen *g, AstNode *node, Scope *parent, ZigVar *var);
ScopeCImport *create_cimport_scope(CodeGen *g, AstNode *node, Scope *parent);
ScopeLoop *create_loop_scope(CodeGen *g, AstNode *node, Scope *parent);
ScopeSuspend *create_suspend_scope(CodeGen *g, AstNode *node, Scope *parent);
ScopeFnDef *create_fndef_scope(CodeGen *g, AstNode *node, Scope *parent, ZigFn *fn_entry);
ScopeDecls *create_decls_scope(CodeGen *g, AstNode *node, Scope *parent, ZigType *container_type, ImportTableEntry *import);
Scope *create_comptime_scope(CodeGen *g, AstNode *node, Scope *parent);
Scope *create_coro_prelude_scope(CodeGen *g, AstNode *node, Scope *parent);
Scope *create_runtime_scope(CodeGen *g, AstNode *node, Scope *parent, IrInstruction *is_comptime);

void init_const_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str);
ConstExprValue *create_const_str_lit(CodeGen *g, Buf *str);
Expand Down
48 changes: 27 additions & 21 deletions src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5336,7 +5336,7 @@ static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent

static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *array_const_val, size_t index) {
expand_undef_array(g, array_const_val);
ConstParent *parent = &array_const_val->data.x_array.s_none.parent;
ConstParent *parent = &array_const_val->data.x_array.data.s_none.parent;
LLVMValueRef base_ptr = gen_parent_ptr(g, array_const_val, parent);

LLVMTypeKind el_type = LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(base_ptr)));
Expand Down Expand Up @@ -5716,23 +5716,29 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
case ZigTypeIdArray:
{
uint64_t len = type_entry->data.array.len;
if (const_val->data.x_array.special == ConstArraySpecialUndef) {
return LLVMGetUndef(type_entry->type_ref);
}

LLVMValueRef *values = allocate<LLVMValueRef>(len);
LLVMTypeRef element_type_ref = type_entry->data.array.child_type->type_ref;
bool make_unnamed_struct = false;
for (uint64_t i = 0; i < len; i += 1) {
ConstExprValue *elem_value = &const_val->data.x_array.s_none.elements[i];
LLVMValueRef val = gen_const_val(g, elem_value, "");
values[i] = val;
make_unnamed_struct = make_unnamed_struct || is_llvm_value_unnamed_type(elem_value->type, val);
}
if (make_unnamed_struct) {
return LLVMConstStruct(values, len, true);
} else {
return LLVMConstArray(element_type_ref, values, (unsigned)len);
switch (const_val->data.x_array.special) {
case ConstArraySpecialUndef:
return LLVMGetUndef(type_entry->type_ref);
case ConstArraySpecialNone: {
LLVMValueRef *values = allocate<LLVMValueRef>(len);
LLVMTypeRef element_type_ref = type_entry->data.array.child_type->type_ref;
bool make_unnamed_struct = false;
for (uint64_t i = 0; i < len; i += 1) {
ConstExprValue *elem_value = &const_val->data.x_array.data.s_none.elements[i];
LLVMValueRef val = gen_const_val(g, elem_value, "");
values[i] = val;
make_unnamed_struct = make_unnamed_struct || is_llvm_value_unnamed_type(elem_value->type, val);
}
if (make_unnamed_struct) {
return LLVMConstStruct(values, len, true);
} else {
return LLVMConstArray(element_type_ref, values, (unsigned)len);
}
}
case ConstArraySpecialBuf: {
Buf *buf = const_val->data.x_array.data.s_buf;
return LLVMConstString(buf_ptr(buf), (unsigned)buf_len(buf), true);
}
}
}
case ZigTypeIdUnion:
Expand Down Expand Up @@ -7278,7 +7284,7 @@ void codegen_translate_c(CodeGen *g, Buf *full_path) {
import->source_code = nullptr;
import->path = full_path;
g->root_import = import;
import->decls_scope = create_decls_scope(nullptr, nullptr, nullptr, import);
import->decls_scope = create_decls_scope(g, nullptr, nullptr, nullptr, import);

init(g);

Expand Down Expand Up @@ -7352,12 +7358,12 @@ static void create_test_compile_var_and_add_test_runner(CodeGen *g) {
ConstExprValue *test_fn_array = create_const_vals(1);
test_fn_array->type = get_array_type(g, struct_type, g->test_fns.length);
test_fn_array->special = ConstValSpecialStatic;
test_fn_array->data.x_array.s_none.elements = create_const_vals(g->test_fns.length);
test_fn_array->data.x_array.data.s_none.elements = create_const_vals(g->test_fns.length);

for (size_t i = 0; i < g->test_fns.length; i += 1) {
ZigFn *test_fn_entry = g->test_fns.at(i);

ConstExprValue *this_val = &test_fn_array->data.x_array.s_none.elements[i];
ConstExprValue *this_val = &test_fn_array->data.x_array.data.s_none.elements[i];
this_val->special = ConstValSpecialStatic;
this_val->type = struct_type;
this_val->data.x_struct.parent.id = ConstParentIdArray;
Expand Down
Loading

0 comments on commit f8fe517

Please sign in to comment.