Skip to content

Commit

Permalink
ability to set tag values of enums
Browse files Browse the repository at this point in the history
also remove support for enums with 0 values

closes #305
  • Loading branch information
andrewrk committed Dec 3, 2017
1 parent 98237f7 commit 137c8f5
Show file tree
Hide file tree
Showing 13 changed files with 451 additions and 146 deletions.
2 changes: 1 addition & 1 deletion doc/langref.html.in
Expand Up @@ -5709,7 +5709,7 @@ VariableDeclaration = option("comptime") ("var" | "const") Symbol option(":" Typ

ContainerMember = (ContainerField | FnDef | GlobalVarDecl)

ContainerField = Symbol option(":" Expression) ","
ContainerField = Symbol option(":" PrefixOpExpression option("=" PrefixOpExpression ","

UseDecl = "use" Expression ";"

Expand Down
10 changes: 6 additions & 4 deletions src/all_types.hpp
Expand Up @@ -98,7 +98,7 @@ struct ConstParent {
};

struct ConstEnumValue {
uint64_t tag;
BigInt tag;
ConstExprValue *payload;
};

Expand All @@ -108,7 +108,7 @@ struct ConstStructValue {
};

struct ConstUnionValue {
uint64_t tag;
BigInt tag;
ConstExprValue *payload;
ConstParent parent;
};
Expand Down Expand Up @@ -346,14 +346,14 @@ struct TldCompTime {
struct TypeEnumField {
Buf *name;
TypeTableEntry *type_entry;
uint32_t value;
BigInt value;
uint32_t gen_index;
};

struct TypeUnionField {
Buf *name;
TypeTableEntry *type_entry;
uint32_t value;
BigInt value;
uint32_t gen_index;
};

Expand Down Expand Up @@ -780,6 +780,7 @@ struct AstNodeStructField {
VisibMod visib_mod;
Buf *name;
AstNode *type;
AstNode *value;
};

struct AstNodeStringLiteral {
Expand Down Expand Up @@ -1014,6 +1015,7 @@ struct TypeTableEntryEnum {
TypeEnumField *fields;
bool is_invalid; // true if any fields are invalid
TypeTableEntry *tag_type;
TypeTableEntry *tag_int_type;
LLVMTypeRef union_type_ref;

ScopeDecls *decls_scope;
Expand Down
234 changes: 182 additions & 52 deletions src/analyze.cpp

Large diffs are not rendered by default.

9 changes: 7 additions & 2 deletions src/analyze.hpp
Expand Up @@ -64,6 +64,8 @@ TypeStructField *find_struct_type_field(TypeTableEntry *type_entry, Buf *name);
ScopeDecls *get_container_scope(TypeTableEntry *type_entry);
TypeEnumField *find_enum_type_field(TypeTableEntry *enum_type, Buf *name);
TypeUnionField *find_union_type_field(TypeTableEntry *type_entry, Buf *name);
TypeEnumField *find_enum_field_by_tag(TypeTableEntry *enum_type, const BigInt *tag);

bool is_container_ref(TypeTableEntry *type_entry);
void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node);
void scan_import(CodeGen *g, ImportTableEntry *import);
Expand Down Expand Up @@ -109,6 +111,9 @@ ConstExprValue *create_const_str_lit(CodeGen *g, Buf *str);
void init_const_c_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *c_str);
ConstExprValue *create_const_c_str_lit(CodeGen *g, Buf *c_str);

void init_const_bigint(ConstExprValue *const_val, TypeTableEntry *type, const BigInt *bigint);
ConstExprValue *create_const_bigint(TypeTableEntry *type, const BigInt *bigint);

void init_const_unsigned_negative(ConstExprValue *const_val, TypeTableEntry *type, uint64_t x, bool negative);
ConstExprValue *create_const_unsigned_negative(TypeTableEntry *type, uint64_t x, bool negative);

Expand All @@ -121,8 +126,8 @@ ConstExprValue *create_const_usize(CodeGen *g, uint64_t x);
void init_const_float(ConstExprValue *const_val, TypeTableEntry *type, double value);
ConstExprValue *create_const_float(TypeTableEntry *type, double value);

void init_const_enum_tag(ConstExprValue *const_val, TypeTableEntry *type, uint64_t tag);
ConstExprValue *create_const_enum_tag(TypeTableEntry *type, uint64_t tag);
void init_const_enum_tag(ConstExprValue *const_val, TypeTableEntry *type, const BigInt *tag);
ConstExprValue *create_const_enum_tag(TypeTableEntry *type, const BigInt *tag);

void init_const_bool(CodeGen *g, ConstExprValue *const_val, bool value);
ConstExprValue *create_const_bool(CodeGen *g, bool value);
Expand Down
4 changes: 4 additions & 0 deletions src/ast_render.cpp
Expand Up @@ -677,6 +677,10 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
fprintf(ar->f, ": ");
render_node_grouped(ar, field_node->data.struct_field.type);
}
if (field_node->data.struct_field.value != nullptr) {
fprintf(ar->f, "= ");
render_node_grouped(ar, field_node->data.struct_field.value);
}
fprintf(ar->f, ",\n");
}

Expand Down
32 changes: 32 additions & 0 deletions src/bigint.cpp
Expand Up @@ -1224,3 +1224,35 @@ Cmp bigint_cmp_zero(const BigInt *op) {
}
return op->is_negative ? CmpLT : CmpGT;
}

uint32_t bigint_hash(BigInt x) {
if (x.digit_count == 0) {
return 0;
} else {
return bigint_ptr(&x)[0];
}
}

bool bigint_eql(BigInt a, BigInt b) {
return bigint_cmp(&a, &b) == CmpEQ;
}

void bigint_incr(BigInt *x) {
if (x->digit_count == 0) {
bigint_init_unsigned(x, 1);
return;
}

if (x->digit_count == 1 && x->data.digit != UINT64_MAX) {
x->data.digit += 1;
return;
}

BigInt copy;
bigint_init_bigint(&copy, x);

BigInt one;
bigint_init_unsigned(&one, 1);

bigint_add(x, &copy, &one);
}
5 changes: 5 additions & 0 deletions src/bigint.hpp
Expand Up @@ -88,6 +88,11 @@ size_t bigint_bits_needed(const BigInt *op);
// convenience functions
Cmp bigint_cmp_zero(const BigInt *op);

void bigint_incr(BigInt *value);

bool mul_u64_overflow(uint64_t op1, uint64_t op2, uint64_t *result);

uint32_t bigint_hash(BigInt x);
bool bigint_eql(BigInt a, BigInt b);

#endif
31 changes: 19 additions & 12 deletions src/codegen.cpp
Expand Up @@ -1362,8 +1362,12 @@ static LLVMValueRef bigint_to_llvm_const(LLVMTypeRef type_ref, BigInt *bigint) {
if (bigint->digit_count == 0) {
return LLVMConstNull(type_ref);
}
LLVMValueRef unsigned_val = LLVMConstIntOfArbitraryPrecision(type_ref,
bigint->digit_count, bigint_ptr(bigint));
LLVMValueRef unsigned_val;
if (bigint->digit_count == 1) {
unsigned_val = LLVMConstInt(type_ref, bigint_ptr(bigint)[0], false);
} else {
unsigned_val = LLVMConstIntOfArbitraryPrecision(type_ref, bigint->digit_count, bigint_ptr(bigint));
}
if (bigint->is_negative) {
return LLVMConstNeg(unsigned_val);
} else {
Expand Down Expand Up @@ -2420,9 +2424,10 @@ static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executab
if (ir_want_debug_safety(g, &instruction->base)) {
LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, union_ptr, union_type->data.unionation.gen_tag_index, "");
LLVMValueRef tag_value = gen_load_untyped(g, tag_field_ptr, 0, false, "");
LLVMValueRef expected_tag_value = LLVMConstInt(union_type->data.unionation.tag_type->type_ref,
field->value, false);


LLVMValueRef expected_tag_value = bigint_to_llvm_const(union_type->data.unionation.tag_type->type_ref,
&field->value);
LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnionCheckOk");
LLVMBasicBlockRef bad_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnionCheckFail");
LLVMValueRef ok_val = LLVMBuildICmp(g->builder, LLVMIntEQ, tag_value, expected_tag_value, "");
Expand Down Expand Up @@ -3364,9 +3369,9 @@ static LLVMValueRef ir_render_enum_tag(CodeGen *g, IrExecutable *executable, IrI

static LLVMValueRef ir_render_init_enum(CodeGen *g, IrExecutable *executable, IrInstructionInitEnum *instruction) {
TypeTableEntry *enum_type = instruction->enum_type;
uint32_t value = instruction->field->value;
LLVMTypeRef tag_type_ref = enum_type->data.enumeration.tag_type->type_ref;
LLVMValueRef tag_value = LLVMConstInt(tag_type_ref, value, false);

LLVMValueRef tag_value = bigint_to_llvm_const(tag_type_ref, &instruction->field->value);

if (enum_type->data.enumeration.gen_field_count == 0)
return tag_value;
Expand Down Expand Up @@ -3429,8 +3434,9 @@ static LLVMValueRef ir_render_union_init(CodeGen *g, IrExecutable *executable, I
if (union_type->data.unionation.gen_tag_index != SIZE_MAX) {
LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr,
union_type->data.unionation.gen_tag_index, "");
LLVMValueRef tag_value = LLVMConstInt(union_type->data.unionation.tag_type->type_ref,
type_union_field->value, false);

LLVMValueRef tag_value = bigint_to_llvm_const(union_type->data.unionation.tag_type->type_ref,
&type_union_field->value);
gen_store_untyped(g, tag_value, tag_field_ptr, 0, false);

uncasted_union_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr,
Expand Down Expand Up @@ -4039,7 +4045,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
return union_value_ref;
}

LLVMValueRef tag_value = LLVMConstInt(type_entry->data.unionation.tag_type->type_ref, const_val->data.x_union.tag, false);
LLVMValueRef tag_value = bigint_to_llvm_const(type_entry->data.unionation.tag_type->type_ref,
&const_val->data.x_union.tag);

LLVMValueRef fields[2];
fields[type_entry->data.unionation.gen_union_index] = union_value_ref;
Expand All @@ -4055,13 +4062,13 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
case TypeTableEntryIdEnum:
{
LLVMTypeRef tag_type_ref = type_entry->data.enumeration.tag_type->type_ref;
LLVMValueRef tag_value = LLVMConstInt(tag_type_ref, const_val->data.x_enum.tag, false);
LLVMValueRef tag_value = bigint_to_llvm_const(tag_type_ref, &const_val->data.x_enum.tag);
if (type_entry->data.enumeration.gen_field_count == 0) {
return tag_value;
} else {
LLVMTypeRef union_type_ref = type_entry->data.enumeration.union_type_ref;
TypeEnumField *enum_field = &type_entry->data.enumeration.fields[const_val->data.x_enum.tag];
assert(enum_field->value == const_val->data.x_enum.tag);
TypeEnumField *enum_field = find_enum_field_by_tag(type_entry, &const_val->data.x_enum.tag);
assert(bigint_cmp(&enum_field->value, &const_val->data.x_enum.tag) == CmpEQ);
LLVMValueRef union_value;

bool make_unnamed_struct;
Expand Down

0 comments on commit 137c8f5

Please sign in to comment.