mirror of
https://github.com/ziglang/zig.git
synced 2025-02-02 12:11:56 +00:00
parent
bf67427c67
commit
bf57d8a7e3
@ -9,9 +9,7 @@ TopLevelItem = ErrorValueDecl | CompTimeExpression(Block) | TopLevelDecl | TestD
|
||||
|
||||
TestDecl = "test" String Block
|
||||
|
||||
TopLevelDecl = option(VisibleMod) (FnDef | ExternDecl | GlobalVarDecl | TypeDecl | UseDecl)
|
||||
|
||||
TypeDecl = "type" Symbol "=" TypeExpr ";"
|
||||
TopLevelDecl = option(VisibleMod) (FnDef | ExternDecl | GlobalVarDecl | UseDecl)
|
||||
|
||||
ErrorValueDecl = "error" Symbol ";"
|
||||
|
||||
@ -155,7 +153,7 @@ GotoExpression = "goto" Symbol
|
||||
|
||||
GroupedExpression = "(" Expression ")"
|
||||
|
||||
KeywordLiteral = "true" | "false" | "null" | "break" | "continue" | "undefined" | "error" | "type" | "this" | "unreachable"
|
||||
KeywordLiteral = "true" | "false" | "null" | "break" | "continue" | "undefined" | "error" | "this" | "unreachable"
|
||||
|
||||
ContainerDecl = option("extern" | "packed") ("struct" | "enum" | "union") "{" many(ContainerMember) "}"
|
||||
```
|
||||
|
@ -254,7 +254,6 @@ enum TldId {
|
||||
TldIdVar,
|
||||
TldIdFn,
|
||||
TldIdContainer,
|
||||
TldIdTypeDef,
|
||||
TldIdCompTime,
|
||||
};
|
||||
|
||||
@ -303,12 +302,6 @@ struct TldContainer {
|
||||
TypeTableEntry *type_entry;
|
||||
};
|
||||
|
||||
struct TldTypeDef {
|
||||
Tld base;
|
||||
|
||||
TypeTableEntry *type_entry;
|
||||
};
|
||||
|
||||
struct TldCompTime {
|
||||
Tld base;
|
||||
};
|
||||
@ -330,7 +323,6 @@ enum NodeType {
|
||||
NodeTypeReturnExpr,
|
||||
NodeTypeDefer,
|
||||
NodeTypeVariableDeclaration,
|
||||
NodeTypeTypeDecl,
|
||||
NodeTypeErrorValueDecl,
|
||||
NodeTypeTestDecl,
|
||||
NodeTypeBinOpExpr,
|
||||
@ -369,7 +361,6 @@ enum NodeType {
|
||||
NodeTypeStructValueField,
|
||||
NodeTypeArrayType,
|
||||
NodeTypeErrorType,
|
||||
NodeTypeTypeLiteral,
|
||||
NodeTypeVarLiteral,
|
||||
NodeTypeTryExpr,
|
||||
NodeTypeInlineExpr,
|
||||
@ -448,12 +439,6 @@ struct AstNodeVariableDeclaration {
|
||||
AstNode *expr;
|
||||
};
|
||||
|
||||
struct AstNodeTypeDecl {
|
||||
VisibMod visib_mod;
|
||||
Buf *symbol;
|
||||
AstNode *child_type;
|
||||
};
|
||||
|
||||
struct AstNodeErrorValueDecl {
|
||||
Buf *name;
|
||||
|
||||
@ -790,9 +775,6 @@ struct AstNodeArrayType {
|
||||
struct AstNodeErrorType {
|
||||
};
|
||||
|
||||
struct AstNodeTypeLiteral {
|
||||
};
|
||||
|
||||
struct AstNodeVarLiteral {
|
||||
};
|
||||
|
||||
@ -816,7 +798,6 @@ struct AstNode {
|
||||
AstNodeReturnExpr return_expr;
|
||||
AstNodeDefer defer;
|
||||
AstNodeVariableDeclaration variable_declaration;
|
||||
AstNodeTypeDecl type_decl;
|
||||
AstNodeErrorValueDecl error_value_decl;
|
||||
AstNodeTestDecl test_decl;
|
||||
AstNodeBinOpExpr bin_op_expr;
|
||||
@ -856,7 +837,6 @@ struct AstNode {
|
||||
AstNodeUnreachableExpr unreachable_expr;
|
||||
AstNodeArrayType array_type;
|
||||
AstNodeErrorType error_type;
|
||||
AstNodeTypeLiteral type_literal;
|
||||
AstNodeVarLiteral var_literal;
|
||||
AstNodeInlineExpr inline_expr;
|
||||
} data;
|
||||
@ -1026,11 +1006,6 @@ struct TypeTableEntryBoundFn {
|
||||
TypeTableEntry *fn_type;
|
||||
};
|
||||
|
||||
struct TypeTableEntryTypeDecl {
|
||||
TypeTableEntry *child_type;
|
||||
TypeTableEntry *canonical_type;
|
||||
};
|
||||
|
||||
enum TypeTableEntryId {
|
||||
TypeTableEntryIdInvalid,
|
||||
TypeTableEntryIdVar,
|
||||
@ -1054,11 +1029,11 @@ enum TypeTableEntryId {
|
||||
TypeTableEntryIdEnumTag,
|
||||
TypeTableEntryIdUnion,
|
||||
TypeTableEntryIdFn,
|
||||
TypeTableEntryIdTypeDecl,
|
||||
TypeTableEntryIdNamespace,
|
||||
TypeTableEntryIdBlock,
|
||||
TypeTableEntryIdBoundFn,
|
||||
TypeTableEntryIdArgTuple,
|
||||
TypeTableEntryIdOpaque,
|
||||
};
|
||||
|
||||
struct TypeTableEntry {
|
||||
@ -1083,7 +1058,6 @@ struct TypeTableEntry {
|
||||
TypeTableEntryEnumTag enum_tag;
|
||||
TypeTableEntryUnion unionation;
|
||||
TypeTableEntryFn fn;
|
||||
TypeTableEntryTypeDecl type_decl;
|
||||
TypeTableEntryBoundFn bound_fn;
|
||||
} data;
|
||||
|
||||
|
190
src/analyze.cpp
190
src/analyze.cpp
@ -186,6 +186,8 @@ bool type_is_complete(TypeTableEntry *type_entry) {
|
||||
return type_entry->data.enumeration.complete;
|
||||
case TypeTableEntryIdUnion:
|
||||
return type_entry->data.unionation.complete;
|
||||
case TypeTableEntryIdOpaque:
|
||||
return false;
|
||||
case TypeTableEntryIdMetaType:
|
||||
case TypeTableEntryIdVoid:
|
||||
case TypeTableEntryIdBool:
|
||||
@ -202,7 +204,6 @@ bool type_is_complete(TypeTableEntry *type_entry) {
|
||||
case TypeTableEntryIdErrorUnion:
|
||||
case TypeTableEntryIdPureError:
|
||||
case TypeTableEntryIdFn:
|
||||
case TypeTableEntryIdTypeDecl:
|
||||
case TypeTableEntryIdNamespace:
|
||||
case TypeTableEntryIdBlock:
|
||||
case TypeTableEntryIdBoundFn:
|
||||
@ -240,12 +241,12 @@ bool type_has_zero_bits_known(TypeTableEntry *type_entry) {
|
||||
case TypeTableEntryIdErrorUnion:
|
||||
case TypeTableEntryIdPureError:
|
||||
case TypeTableEntryIdFn:
|
||||
case TypeTableEntryIdTypeDecl:
|
||||
case TypeTableEntryIdNamespace:
|
||||
case TypeTableEntryIdBlock:
|
||||
case TypeTableEntryIdBoundFn:
|
||||
case TypeTableEntryIdEnumTag:
|
||||
case TypeTableEntryIdArgTuple:
|
||||
case TypeTableEntryIdOpaque:
|
||||
return true;
|
||||
}
|
||||
zig_unreachable();
|
||||
@ -254,18 +255,17 @@ bool type_has_zero_bits_known(TypeTableEntry *type_entry) {
|
||||
|
||||
uint64_t type_size(CodeGen *g, TypeTableEntry *type_entry) {
|
||||
assert(type_is_complete(type_entry));
|
||||
TypeTableEntry *canon_type = get_underlying_type(type_entry);
|
||||
|
||||
if (!type_has_bits(type_entry))
|
||||
return 0;
|
||||
|
||||
if (canon_type->id == TypeTableEntryIdStruct && canon_type->data.structure.layout == ContainerLayoutPacked) {
|
||||
if (type_entry->id == TypeTableEntryIdStruct && type_entry->data.structure.layout == ContainerLayoutPacked) {
|
||||
uint64_t size_in_bits = type_size_bits(g, type_entry);
|
||||
return (size_in_bits + 7) / 8;
|
||||
} else if (canon_type->id == TypeTableEntryIdArray) {
|
||||
TypeTableEntry *canon_child_type = get_underlying_type(canon_type->data.array.child_type);
|
||||
if (canon_child_type->id == TypeTableEntryIdStruct &&
|
||||
canon_child_type->data.structure.layout == ContainerLayoutPacked)
|
||||
} else if (type_entry->id == TypeTableEntryIdArray) {
|
||||
TypeTableEntry *child_type = type_entry->data.array.child_type;
|
||||
if (child_type->id == TypeTableEntryIdStruct &&
|
||||
child_type->data.structure.layout == ContainerLayoutPacked)
|
||||
{
|
||||
uint64_t size_in_bits = type_size_bits(g, type_entry);
|
||||
return (size_in_bits + 7) / 8;
|
||||
@ -277,27 +277,26 @@ uint64_t type_size(CodeGen *g, TypeTableEntry *type_entry) {
|
||||
|
||||
uint64_t type_size_bits(CodeGen *g, TypeTableEntry *type_entry) {
|
||||
assert(type_is_complete(type_entry));
|
||||
TypeTableEntry *canon_type = get_underlying_type(type_entry);
|
||||
|
||||
if (!type_has_bits(type_entry))
|
||||
return 0;
|
||||
|
||||
if (canon_type->id == TypeTableEntryIdStruct && canon_type->data.structure.layout == ContainerLayoutPacked) {
|
||||
if (type_entry->id == TypeTableEntryIdStruct && type_entry->data.structure.layout == ContainerLayoutPacked) {
|
||||
uint64_t result = 0;
|
||||
for (size_t i = 0; i < canon_type->data.structure.src_field_count; i += 1) {
|
||||
result += type_size_bits(g, canon_type->data.structure.fields[i].type_entry);
|
||||
for (size_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) {
|
||||
result += type_size_bits(g, type_entry->data.structure.fields[i].type_entry);
|
||||
}
|
||||
return result;
|
||||
} else if (canon_type->id == TypeTableEntryIdArray) {
|
||||
TypeTableEntry *canon_child_type = get_underlying_type(canon_type->data.array.child_type);
|
||||
if (canon_child_type->id == TypeTableEntryIdStruct &&
|
||||
canon_child_type->data.structure.layout == ContainerLayoutPacked)
|
||||
} else if (type_entry->id == TypeTableEntryIdArray) {
|
||||
TypeTableEntry *child_type = type_entry->data.array.child_type;
|
||||
if (child_type->id == TypeTableEntryIdStruct &&
|
||||
child_type->data.structure.layout == ContainerLayoutPacked)
|
||||
{
|
||||
return canon_type->data.array.len * type_size_bits(g, canon_child_type);
|
||||
return type_entry->data.array.len * type_size_bits(g, child_type);
|
||||
}
|
||||
}
|
||||
|
||||
return LLVMSizeOfTypeInBits(g->target_data_ref, canon_type->type_ref);
|
||||
return LLVMSizeOfTypeInBits(g->target_data_ref, type_entry->type_ref);
|
||||
}
|
||||
|
||||
static bool type_is_copyable(CodeGen *g, TypeTableEntry *type_entry) {
|
||||
@ -360,10 +359,9 @@ TypeTableEntry *get_pointer_to_type_extra(CodeGen *g, TypeTableEntry *child_type
|
||||
bit_offset + unaligned_bit_count, const_str, volatile_str, buf_ptr(&child_type->name));
|
||||
}
|
||||
|
||||
TypeTableEntry *canon_child_type = get_underlying_type(child_type);
|
||||
assert(canon_child_type->id != TypeTableEntryIdInvalid);
|
||||
assert(child_type->id != TypeTableEntryIdInvalid);
|
||||
|
||||
entry->zero_bits = !type_has_bits(canon_child_type);
|
||||
entry->zero_bits = !type_has_bits(child_type);
|
||||
|
||||
if (!entry->zero_bits) {
|
||||
entry->type_ref = LLVMPointerType(child_type->type_ref, 0);
|
||||
@ -766,17 +764,22 @@ TypeTableEntry *get_slice_type(CodeGen *g, TypeTableEntry *child_type, bool is_c
|
||||
}
|
||||
}
|
||||
|
||||
TypeTableEntry *get_typedecl_type(CodeGen *g, const char *name, TypeTableEntry *child_type) {
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdTypeDecl);
|
||||
TypeTableEntry *get_opaque_type(CodeGen *g, Scope *scope, AstNode *source_node, const char *name) {
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdOpaque);
|
||||
|
||||
buf_init_from_str(&entry->name, name);
|
||||
|
||||
entry->is_copyable = type_is_copyable(g, child_type);
|
||||
entry->type_ref = child_type->type_ref;
|
||||
entry->di_type = child_type->di_type;
|
||||
entry->zero_bits = child_type->zero_bits;
|
||||
entry->data.type_decl.child_type = child_type;
|
||||
entry->data.type_decl.canonical_type = get_underlying_type(child_type);
|
||||
ImportTableEntry *import = scope ? get_scope_import(scope) : nullptr;
|
||||
unsigned line = source_node ? (unsigned)(source_node->line + 1) : 0;
|
||||
|
||||
entry->is_copyable = false;
|
||||
entry->type_ref = LLVMInt8Type();
|
||||
entry->di_type = ZigLLVMCreateDebugForwardDeclType(g->dbuilder,
|
||||
ZigLLVMTag_DW_structure_type(), buf_ptr(&entry->name),
|
||||
import ? ZigLLVMFileToScope(import->di_file) : nullptr,
|
||||
import ? import->di_file : nullptr,
|
||||
line);
|
||||
entry->zero_bits = false;
|
||||
|
||||
return entry;
|
||||
}
|
||||
@ -968,14 +971,6 @@ TypeTableEntry *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKi
|
||||
return entry;
|
||||
}
|
||||
|
||||
TypeTableEntry *get_underlying_type(TypeTableEntry *type_entry) {
|
||||
if (type_entry->id == TypeTableEntryIdTypeDecl) {
|
||||
return type_entry->data.type_decl.canonical_type;
|
||||
} else {
|
||||
return type_entry;
|
||||
}
|
||||
}
|
||||
|
||||
static IrInstruction *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, TypeTableEntry *type_entry, Buf *type_name) {
|
||||
size_t backward_branch_count = 0;
|
||||
return ir_eval_const_value(g, scope, node, type_entry,
|
||||
@ -1066,6 +1061,7 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c
|
||||
case TypeTableEntryIdUndefLit:
|
||||
case TypeTableEntryIdNullLit:
|
||||
case TypeTableEntryIdArgTuple:
|
||||
case TypeTableEntryIdOpaque:
|
||||
add_node_error(g, param_node->data.param_decl.type,
|
||||
buf_sprintf("parameter of type '%s' not allowed", buf_ptr(&type_entry->name)));
|
||||
return g->builtin_types.entry_invalid;
|
||||
@ -1099,7 +1095,6 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c
|
||||
case TypeTableEntryIdEnum:
|
||||
case TypeTableEntryIdUnion:
|
||||
case TypeTableEntryIdFn:
|
||||
case TypeTableEntryIdTypeDecl:
|
||||
case TypeTableEntryIdEnumTag:
|
||||
ensure_complete_type(g, type_entry);
|
||||
if (!fn_type_id.is_extern && !type_is_copyable(g, type_entry)) {
|
||||
@ -1123,6 +1118,7 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c
|
||||
case TypeTableEntryIdUndefLit:
|
||||
case TypeTableEntryIdNullLit:
|
||||
case TypeTableEntryIdArgTuple:
|
||||
case TypeTableEntryIdOpaque:
|
||||
add_node_error(g, fn_proto->return_type,
|
||||
buf_sprintf("return type '%s' not allowed", buf_ptr(&fn_type_id.return_type->name)));
|
||||
return g->builtin_types.entry_invalid;
|
||||
@ -1155,7 +1151,6 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c
|
||||
case TypeTableEntryIdEnum:
|
||||
case TypeTableEntryIdUnion:
|
||||
case TypeTableEntryIdFn:
|
||||
case TypeTableEntryIdTypeDecl:
|
||||
case TypeTableEntryIdEnumTag:
|
||||
break;
|
||||
}
|
||||
@ -1173,8 +1168,6 @@ bool type_is_invalid(TypeTableEntry *type_entry) {
|
||||
return type_entry->data.enumeration.is_invalid;
|
||||
case TypeTableEntryIdUnion:
|
||||
return type_entry->data.unionation.is_invalid;
|
||||
case TypeTableEntryIdTypeDecl:
|
||||
return type_is_invalid(type_entry->data.type_decl.canonical_type);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@ -1380,8 +1373,7 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) {
|
||||
}
|
||||
|
||||
static bool type_allowed_in_packed_struct(TypeTableEntry *type_entry) {
|
||||
TypeTableEntry *canon_type = get_underlying_type(type_entry);
|
||||
switch (canon_type->id) {
|
||||
switch (type_entry->id) {
|
||||
case TypeTableEntryIdInvalid:
|
||||
case TypeTableEntryIdVar:
|
||||
zig_unreachable();
|
||||
@ -1395,11 +1387,11 @@ static bool type_allowed_in_packed_struct(TypeTableEntry *type_entry) {
|
||||
case TypeTableEntryIdPureError:
|
||||
case TypeTableEntryIdEnum:
|
||||
case TypeTableEntryIdEnumTag:
|
||||
case TypeTableEntryIdTypeDecl:
|
||||
case TypeTableEntryIdNamespace:
|
||||
case TypeTableEntryIdBlock:
|
||||
case TypeTableEntryIdBoundFn:
|
||||
case TypeTableEntryIdArgTuple:
|
||||
case TypeTableEntryIdOpaque:
|
||||
return false;
|
||||
case TypeTableEntryIdVoid:
|
||||
case TypeTableEntryIdBool:
|
||||
@ -1411,11 +1403,11 @@ static bool type_allowed_in_packed_struct(TypeTableEntry *type_entry) {
|
||||
case TypeTableEntryIdFn:
|
||||
return true;
|
||||
case TypeTableEntryIdStruct:
|
||||
return canon_type->data.structure.layout == ContainerLayoutPacked;
|
||||
return type_entry->data.structure.layout == ContainerLayoutPacked;
|
||||
case TypeTableEntryIdMaybe:
|
||||
{
|
||||
TypeTableEntry *canon_child_type = get_underlying_type(canon_type->data.maybe.child_type);
|
||||
return canon_child_type->id == TypeTableEntryIdPointer || canon_child_type->id == TypeTableEntryIdFn;
|
||||
TypeTableEntry *child_type = type_entry->data.maybe.child_type;
|
||||
return child_type->id == TypeTableEntryIdPointer || child_type->id == TypeTableEntryIdFn;
|
||||
}
|
||||
}
|
||||
zig_unreachable();
|
||||
@ -2037,15 +2029,6 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
|
||||
add_top_level_decl(g, decls_scope, &tld_var->base);
|
||||
break;
|
||||
}
|
||||
case NodeTypeTypeDecl:
|
||||
{
|
||||
Buf *name = node->data.type_decl.symbol;
|
||||
VisibMod visib_mod = node->data.type_decl.visib_mod;
|
||||
TldTypeDef *tld_typedef = allocate<TldTypeDef>(1);
|
||||
init_tld(&tld_typedef->base, TldIdTypeDef, name, visib_mod, node, &decls_scope->base);
|
||||
add_top_level_decl(g, decls_scope, &tld_typedef->base);
|
||||
break;
|
||||
}
|
||||
case NodeTypeFnProto:
|
||||
{
|
||||
// if the name is missing, we immediately announce an error
|
||||
@ -2126,7 +2109,6 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
|
||||
case NodeTypeStructValueField:
|
||||
case NodeTypeArrayType:
|
||||
case NodeTypeErrorType:
|
||||
case NodeTypeTypeLiteral:
|
||||
case NodeTypeVarLiteral:
|
||||
case NodeTypeTryExpr:
|
||||
case NodeTypeInlineExpr:
|
||||
@ -2154,10 +2136,7 @@ static void resolve_decl_container(CodeGen *g, TldContainer *tld_container) {
|
||||
}
|
||||
|
||||
TypeTableEntry *validate_var_type(CodeGen *g, AstNode *source_node, TypeTableEntry *type_entry) {
|
||||
TypeTableEntry *underlying_type = get_underlying_type(type_entry);
|
||||
switch (underlying_type->id) {
|
||||
case TypeTableEntryIdTypeDecl:
|
||||
zig_unreachable();
|
||||
switch (type_entry->id) {
|
||||
case TypeTableEntryIdInvalid:
|
||||
return g->builtin_types.entry_invalid;
|
||||
case TypeTableEntryIdUnreachable:
|
||||
@ -2168,8 +2147,9 @@ TypeTableEntry *validate_var_type(CodeGen *g, AstNode *source_node, TypeTableEnt
|
||||
case TypeTableEntryIdNullLit:
|
||||
case TypeTableEntryIdBlock:
|
||||
case TypeTableEntryIdArgTuple:
|
||||
case TypeTableEntryIdOpaque:
|
||||
add_node_error(g, source_node, buf_sprintf("variable of type '%s' not allowed",
|
||||
buf_ptr(&underlying_type->name)));
|
||||
buf_ptr(&type_entry->name)));
|
||||
return g->builtin_types.entry_invalid;
|
||||
case TypeTableEntryIdNamespace:
|
||||
case TypeTableEntryIdMetaType:
|
||||
@ -2328,17 +2308,6 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
|
||||
g->global_vars.append(tld_var);
|
||||
}
|
||||
|
||||
static void resolve_decl_typedef(CodeGen *g, TldTypeDef *tld_typedef) {
|
||||
AstNode *typedef_node = tld_typedef->base.source_node;
|
||||
assert(typedef_node->type == NodeTypeTypeDecl);
|
||||
AstNode *type_node = typedef_node->data.type_decl.child_type;
|
||||
Buf *decl_name = typedef_node->data.type_decl.symbol;
|
||||
|
||||
TypeTableEntry *child_type = analyze_type_expr(g, tld_typedef->base.parent_scope, type_node);
|
||||
tld_typedef->type_entry = (child_type->id == TypeTableEntryIdInvalid) ?
|
||||
child_type : get_typedecl_type(g, buf_ptr(decl_name), child_type);
|
||||
}
|
||||
|
||||
void resolve_top_level_decl(CodeGen *g, Tld *tld, bool pointer_only) {
|
||||
if (tld->resolution != TldResolutionUnresolved)
|
||||
return;
|
||||
@ -2370,12 +2339,6 @@ void resolve_top_level_decl(CodeGen *g, Tld *tld, bool pointer_only) {
|
||||
resolve_decl_container(g, tld_container);
|
||||
break;
|
||||
}
|
||||
case TldIdTypeDef:
|
||||
{
|
||||
TldTypeDef *tld_typedef = (TldTypeDef *)tld;
|
||||
resolve_decl_typedef(g, tld_typedef);
|
||||
break;
|
||||
}
|
||||
case TldIdCompTime:
|
||||
{
|
||||
TldCompTime *tld_comptime = (TldCompTime *)tld;
|
||||
@ -2589,6 +2552,7 @@ static bool is_container(TypeTableEntry *type_entry) {
|
||||
switch (type_entry->id) {
|
||||
case TypeTableEntryIdInvalid:
|
||||
case TypeTableEntryIdVar:
|
||||
case TypeTableEntryIdOpaque:
|
||||
zig_unreachable();
|
||||
case TypeTableEntryIdStruct:
|
||||
case TypeTableEntryIdEnum:
|
||||
@ -2610,7 +2574,6 @@ static bool is_container(TypeTableEntry *type_entry) {
|
||||
case TypeTableEntryIdErrorUnion:
|
||||
case TypeTableEntryIdPureError:
|
||||
case TypeTableEntryIdFn:
|
||||
case TypeTableEntryIdTypeDecl:
|
||||
case TypeTableEntryIdNamespace:
|
||||
case TypeTableEntryIdBlock:
|
||||
case TypeTableEntryIdBoundFn:
|
||||
@ -2659,7 +2622,6 @@ void resolve_container_type(CodeGen *g, TypeTableEntry *type_entry) {
|
||||
case TypeTableEntryIdErrorUnion:
|
||||
case TypeTableEntryIdPureError:
|
||||
case TypeTableEntryIdFn:
|
||||
case TypeTableEntryIdTypeDecl:
|
||||
case TypeTableEntryIdNamespace:
|
||||
case TypeTableEntryIdBlock:
|
||||
case TypeTableEntryIdBoundFn:
|
||||
@ -2667,6 +2629,7 @@ void resolve_container_type(CodeGen *g, TypeTableEntry *type_entry) {
|
||||
case TypeTableEntryIdVar:
|
||||
case TypeTableEntryIdEnumTag:
|
||||
case TypeTableEntryIdArgTuple:
|
||||
case TypeTableEntryIdOpaque:
|
||||
zig_unreachable();
|
||||
}
|
||||
}
|
||||
@ -3062,6 +3025,7 @@ bool handle_is_ptr(TypeTableEntry *type_entry) {
|
||||
case TypeTableEntryIdBoundFn:
|
||||
case TypeTableEntryIdVar:
|
||||
case TypeTableEntryIdArgTuple:
|
||||
case TypeTableEntryIdOpaque:
|
||||
zig_unreachable();
|
||||
case TypeTableEntryIdUnreachable:
|
||||
case TypeTableEntryIdVoid:
|
||||
@ -3086,8 +3050,6 @@ bool handle_is_ptr(TypeTableEntry *type_entry) {
|
||||
return type_has_bits(type_entry->data.maybe.child_type) &&
|
||||
type_entry->data.maybe.child_type->id != TypeTableEntryIdPointer &&
|
||||
type_entry->data.maybe.child_type->id != TypeTableEntryIdFn;
|
||||
case TypeTableEntryIdTypeDecl:
|
||||
return handle_is_ptr(type_entry->data.type_decl.canonical_type);
|
||||
}
|
||||
zig_unreachable();
|
||||
}
|
||||
@ -3165,6 +3127,8 @@ bool fn_type_id_eql(FnTypeId *a, FnTypeId *b) {
|
||||
static uint32_t hash_const_val(ConstExprValue *const_val) {
|
||||
assert(const_val->special == ConstValSpecialStatic);
|
||||
switch (const_val->type->id) {
|
||||
case TypeTableEntryIdOpaque:
|
||||
zig_unreachable();
|
||||
case TypeTableEntryIdBool:
|
||||
return const_val->data.x_bool ? (uint32_t)127863866 : (uint32_t)215080464;
|
||||
case TypeTableEntryIdMetaType:
|
||||
@ -3254,8 +3218,6 @@ static uint32_t hash_const_val(ConstExprValue *const_val) {
|
||||
case TypeTableEntryIdFn:
|
||||
return hash_ptr(const_val->data.x_fn.fn_entry) +
|
||||
(const_val->data.x_fn.is_inline ? 4133894920 : 3983484790);
|
||||
case TypeTableEntryIdTypeDecl:
|
||||
return hash_ptr(const_val->data.x_type);
|
||||
case TypeTableEntryIdNamespace:
|
||||
return hash_ptr(const_val->data.x_import);
|
||||
case TypeTableEntryIdBlock:
|
||||
@ -3359,10 +3321,10 @@ bool type_has_bits(TypeTableEntry *type_entry) {
|
||||
}
|
||||
|
||||
bool type_requires_comptime(TypeTableEntry *type_entry) {
|
||||
switch (get_underlying_type(type_entry)->id) {
|
||||
switch (type_entry->id) {
|
||||
case TypeTableEntryIdInvalid:
|
||||
case TypeTableEntryIdVar:
|
||||
case TypeTableEntryIdTypeDecl:
|
||||
case TypeTableEntryIdOpaque:
|
||||
zig_unreachable();
|
||||
case TypeTableEntryIdNumLitFloat:
|
||||
case TypeTableEntryIdNumLitInt:
|
||||
@ -3603,14 +3565,14 @@ ConstExprValue *create_const_arg_tuple(CodeGen *g, size_t arg_index_start, size_
|
||||
|
||||
|
||||
void init_const_undefined(CodeGen *g, ConstExprValue *const_val) {
|
||||
TypeTableEntry *canon_wanted_type = get_underlying_type(const_val->type);
|
||||
if (canon_wanted_type->id == TypeTableEntryIdArray) {
|
||||
TypeTableEntry *wanted_type = const_val->type;
|
||||
if (wanted_type->id == TypeTableEntryIdArray) {
|
||||
const_val->special = ConstValSpecialStatic;
|
||||
size_t elem_count = canon_wanted_type->data.array.len;
|
||||
size_t elem_count = wanted_type->data.array.len;
|
||||
const_val->data.x_array.elements = allocate<ConstExprValue>(elem_count);
|
||||
for (size_t i = 0; i < elem_count; i += 1) {
|
||||
ConstExprValue *element_val = &const_val->data.x_array.elements[i];
|
||||
element_val->type = canon_wanted_type->data.array.child_type;
|
||||
element_val->type = wanted_type->data.array.child_type;
|
||||
init_const_undefined(g, element_val);
|
||||
ConstParent *parent = get_const_val_parent(element_val);
|
||||
if (parent != nullptr) {
|
||||
@ -3619,15 +3581,15 @@ void init_const_undefined(CodeGen *g, ConstExprValue *const_val) {
|
||||
parent->data.p_array.elem_index = i;
|
||||
}
|
||||
}
|
||||
} else if (canon_wanted_type->id == TypeTableEntryIdStruct) {
|
||||
ensure_complete_type(g, canon_wanted_type);
|
||||
} else if (wanted_type->id == TypeTableEntryIdStruct) {
|
||||
ensure_complete_type(g, wanted_type);
|
||||
|
||||
const_val->special = ConstValSpecialStatic;
|
||||
size_t field_count = canon_wanted_type->data.structure.src_field_count;
|
||||
size_t field_count = wanted_type->data.structure.src_field_count;
|
||||
const_val->data.x_struct.fields = allocate<ConstExprValue>(field_count);
|
||||
for (size_t i = 0; i < field_count; i += 1) {
|
||||
ConstExprValue *field_val = &const_val->data.x_struct.fields[i];
|
||||
field_val->type = canon_wanted_type->data.structure.fields[i].type_entry;
|
||||
field_val->type = wanted_type->data.structure.fields[i].type_entry;
|
||||
assert(field_val->type);
|
||||
init_const_undefined(g, field_val);
|
||||
ConstParent *parent = get_const_val_parent(field_val);
|
||||
@ -3678,6 +3640,8 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) {
|
||||
assert(a->special == ConstValSpecialStatic);
|
||||
assert(b->special == ConstValSpecialStatic);
|
||||
switch (a->type->id) {
|
||||
case TypeTableEntryIdOpaque:
|
||||
zig_unreachable();
|
||||
case TypeTableEntryIdEnum:
|
||||
{
|
||||
ConstEnumValue *enum1 = &a->data.x_enum;
|
||||
@ -3767,8 +3731,6 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) {
|
||||
}
|
||||
case TypeTableEntryIdErrorUnion:
|
||||
zig_panic("TODO");
|
||||
case TypeTableEntryIdTypeDecl:
|
||||
zig_panic("TODO");
|
||||
case TypeTableEntryIdNamespace:
|
||||
return a->data.x_import == b->data.x_import;
|
||||
case TypeTableEntryIdBlock:
|
||||
@ -3857,9 +3819,9 @@ void render_const_value(Buf *buf, ConstExprValue *const_val) {
|
||||
}
|
||||
assert(const_val->type);
|
||||
|
||||
TypeTableEntry *canon_type = get_underlying_type(const_val->type);
|
||||
switch (canon_type->id) {
|
||||
case TypeTableEntryIdTypeDecl:
|
||||
TypeTableEntry *type_entry = const_val->type;
|
||||
switch (type_entry->id) {
|
||||
case TypeTableEntryIdOpaque:
|
||||
zig_unreachable();
|
||||
case TypeTableEntryIdInvalid:
|
||||
buf_appendf(buf, "(invalid)");
|
||||
@ -3926,7 +3888,7 @@ void render_const_value(Buf *buf, ConstExprValue *const_val) {
|
||||
return;
|
||||
}
|
||||
case ConstPtrSpecialHardCodedAddr:
|
||||
buf_appendf(buf, "(&%s)(%" PRIx64 ")", buf_ptr(&canon_type->data.pointer.child_type->name),
|
||||
buf_appendf(buf, "(&%s)(%" PRIx64 ")", buf_ptr(&type_entry->data.pointer.child_type->name),
|
||||
const_val->data.x_ptr.data.hard_coded_addr.addr);
|
||||
return;
|
||||
case ConstPtrSpecialDiscard:
|
||||
@ -3949,8 +3911,8 @@ void render_const_value(Buf *buf, ConstExprValue *const_val) {
|
||||
}
|
||||
case TypeTableEntryIdArray:
|
||||
{
|
||||
TypeTableEntry *child_type = canon_type->data.array.child_type;
|
||||
uint64_t len = canon_type->data.array.len;
|
||||
TypeTableEntry *child_type = type_entry->data.array.child_type;
|
||||
uint64_t len = type_entry->data.array.len;
|
||||
|
||||
// if it's []u8, assume UTF-8 and output a string
|
||||
if (child_type->id == TypeTableEntryIdInt &&
|
||||
@ -3973,7 +3935,7 @@ void render_const_value(Buf *buf, ConstExprValue *const_val) {
|
||||
return;
|
||||
}
|
||||
|
||||
buf_appendf(buf, "%s{", buf_ptr(&canon_type->name));
|
||||
buf_appendf(buf, "%s{", buf_ptr(&type_entry->name));
|
||||
for (uint64_t i = 0; i < len; i += 1) {
|
||||
if (i != 0)
|
||||
buf_appendf(buf, ",");
|
||||
@ -4021,22 +3983,22 @@ void render_const_value(Buf *buf, ConstExprValue *const_val) {
|
||||
}
|
||||
case TypeTableEntryIdStruct:
|
||||
{
|
||||
buf_appendf(buf, "(struct %s constant)", buf_ptr(&canon_type->name));
|
||||
buf_appendf(buf, "(struct %s constant)", buf_ptr(&type_entry->name));
|
||||
return;
|
||||
}
|
||||
case TypeTableEntryIdEnum:
|
||||
{
|
||||
buf_appendf(buf, "(enum %s constant)", buf_ptr(&canon_type->name));
|
||||
buf_appendf(buf, "(enum %s constant)", buf_ptr(&type_entry->name));
|
||||
return;
|
||||
}
|
||||
case TypeTableEntryIdErrorUnion:
|
||||
{
|
||||
buf_appendf(buf, "(error union %s constant)", buf_ptr(&canon_type->name));
|
||||
buf_appendf(buf, "(error union %s constant)", buf_ptr(&type_entry->name));
|
||||
return;
|
||||
}
|
||||
case TypeTableEntryIdUnion:
|
||||
{
|
||||
buf_appendf(buf, "(union %s constant)", buf_ptr(&canon_type->name));
|
||||
buf_appendf(buf, "(union %s constant)", buf_ptr(&type_entry->name));
|
||||
return;
|
||||
}
|
||||
case TypeTableEntryIdPureError:
|
||||
@ -4046,7 +4008,7 @@ void render_const_value(Buf *buf, ConstExprValue *const_val) {
|
||||
}
|
||||
case TypeTableEntryIdEnumTag:
|
||||
{
|
||||
TypeTableEntry *enum_type = canon_type->data.enum_tag.enum_type;
|
||||
TypeTableEntry *enum_type = type_entry->data.enum_tag.enum_type;
|
||||
TypeEnumField *field = &enum_type->data.enumeration.fields[const_val->data.x_bignum.data.x_uint];
|
||||
buf_appendf(buf, "%s.%s", buf_ptr(&enum_type->name), buf_ptr(field->name));
|
||||
return;
|
||||
@ -4095,6 +4057,7 @@ uint32_t type_id_hash(TypeId x) {
|
||||
switch (x.id) {
|
||||
case TypeTableEntryIdInvalid:
|
||||
case TypeTableEntryIdVar:
|
||||
case TypeTableEntryIdOpaque:
|
||||
case TypeTableEntryIdMetaType:
|
||||
case TypeTableEntryIdVoid:
|
||||
case TypeTableEntryIdBool:
|
||||
@ -4112,7 +4075,6 @@ uint32_t type_id_hash(TypeId x) {
|
||||
case TypeTableEntryIdEnumTag:
|
||||
case TypeTableEntryIdUnion:
|
||||
case TypeTableEntryIdFn:
|
||||
case TypeTableEntryIdTypeDecl:
|
||||
case TypeTableEntryIdNamespace:
|
||||
case TypeTableEntryIdBlock:
|
||||
case TypeTableEntryIdBoundFn:
|
||||
@ -4157,11 +4119,11 @@ bool type_id_eql(TypeId a, TypeId b) {
|
||||
case TypeTableEntryIdEnumTag:
|
||||
case TypeTableEntryIdUnion:
|
||||
case TypeTableEntryIdFn:
|
||||
case TypeTableEntryIdTypeDecl:
|
||||
case TypeTableEntryIdNamespace:
|
||||
case TypeTableEntryIdBlock:
|
||||
case TypeTableEntryIdBoundFn:
|
||||
case TypeTableEntryIdArgTuple:
|
||||
case TypeTableEntryIdOpaque:
|
||||
zig_unreachable();
|
||||
case TypeTableEntryIdPointer:
|
||||
return a.data.pointer.child_type == b.data.pointer.child_type &&
|
||||
@ -4211,10 +4173,10 @@ bool zig_llvm_fn_key_eql(ZigLLVMFnKey a, ZigLLVMFnKey b) {
|
||||
|
||||
ConstParent *get_const_val_parent(ConstExprValue *value) {
|
||||
assert(value->type);
|
||||
TypeTableEntry *canon_type = get_underlying_type(value->type);
|
||||
if (canon_type->id == TypeTableEntryIdArray) {
|
||||
TypeTableEntry *type_entry = value->type;
|
||||
if (type_entry->id == TypeTableEntryIdArray) {
|
||||
return &value->data.x_array.parent;
|
||||
} else if (canon_type->id == TypeTableEntryIdStruct) {
|
||||
} else if (type_entry->id == TypeTableEntryIdStruct) {
|
||||
return &value->data.x_struct.parent;
|
||||
}
|
||||
return nullptr;
|
||||
|
@ -24,7 +24,6 @@ TypeTableEntry **get_int_type_ptr(CodeGen *g, bool is_signed, uint32_t size_in_b
|
||||
TypeTableEntry *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits);
|
||||
TypeTableEntry **get_c_int_type_ptr(CodeGen *g, CIntType c_int_type);
|
||||
TypeTableEntry *get_c_int_type(CodeGen *g, CIntType c_int_type);
|
||||
TypeTableEntry *get_typedecl_type(CodeGen *g, const char *name, TypeTableEntry *child_type);
|
||||
TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id);
|
||||
TypeTableEntry *get_maybe_type(CodeGen *g, TypeTableEntry *child_type);
|
||||
TypeTableEntry *get_array_type(CodeGen *g, TypeTableEntry *child_type, uint64_t array_size);
|
||||
@ -34,11 +33,11 @@ TypeTableEntry *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKi
|
||||
TypeTableEntry *get_smallest_unsigned_int_type(CodeGen *g, uint64_t x);
|
||||
TypeTableEntry *get_error_type(CodeGen *g, TypeTableEntry *child_type);
|
||||
TypeTableEntry *get_bound_fn_type(CodeGen *g, FnTableEntry *fn_entry);
|
||||
TypeTableEntry *get_opaque_type(CodeGen *g, Scope *scope, AstNode *source_node, const char *name);
|
||||
bool handle_is_ptr(TypeTableEntry *type_entry);
|
||||
void find_libc_include_path(CodeGen *g);
|
||||
void find_libc_lib_path(CodeGen *g);
|
||||
|
||||
TypeTableEntry *get_underlying_type(TypeTableEntry *type_entry);
|
||||
bool type_has_bits(TypeTableEntry *type_entry);
|
||||
|
||||
|
||||
|
@ -166,8 +166,6 @@ static const char *node_type_str(NodeType node_type) {
|
||||
return "Defer";
|
||||
case NodeTypeVariableDeclaration:
|
||||
return "VariableDeclaration";
|
||||
case NodeTypeTypeDecl:
|
||||
return "TypeDecl";
|
||||
case NodeTypeErrorValueDecl:
|
||||
return "ErrorValueDecl";
|
||||
case NodeTypeTestDecl:
|
||||
@ -234,8 +232,6 @@ static const char *node_type_str(NodeType node_type) {
|
||||
return "ArrayType";
|
||||
case NodeTypeErrorType:
|
||||
return "ErrorType";
|
||||
case NodeTypeTypeLiteral:
|
||||
return "TypeLiteral";
|
||||
case NodeTypeVarLiteral:
|
||||
return "VarLiteral";
|
||||
case NodeTypeTryExpr:
|
||||
@ -394,7 +390,6 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
|
||||
|
||||
if (child->type == NodeTypeUse ||
|
||||
child->type == NodeTypeVariableDeclaration ||
|
||||
child->type == NodeTypeTypeDecl ||
|
||||
child->type == NodeTypeErrorValueDecl ||
|
||||
child->type == NodeTypeFnProto)
|
||||
{
|
||||
@ -507,14 +502,6 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NodeTypeTypeDecl:
|
||||
{
|
||||
const char *pub_str = visib_mod_string(node->data.type_decl.visib_mod);
|
||||
const char *var_name = buf_ptr(node->data.type_decl.symbol);
|
||||
fprintf(ar->f, "%stype %s = ", pub_str, var_name);
|
||||
render_node_grouped(ar, node->data.type_decl.child_type);
|
||||
break;
|
||||
}
|
||||
case NodeTypeBinOpExpr:
|
||||
if (!grouped) fprintf(ar->f, "(");
|
||||
render_node_ungrouped(ar, node->data.bin_op_expr.op1);
|
||||
@ -668,9 +655,6 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
|
||||
case NodeTypeErrorType:
|
||||
fprintf(ar->f, "error");
|
||||
break;
|
||||
case NodeTypeTypeLiteral:
|
||||
fprintf(ar->f, "type");
|
||||
break;
|
||||
case NodeTypeVarLiteral:
|
||||
fprintf(ar->f, "var");
|
||||
break;
|
||||
@ -1034,6 +1018,12 @@ static void ast_render_tld_var(AstRender *ar, Buf *name, TldVar *tld_var) {
|
||||
fprintf(ar->f, "union {");
|
||||
fprintf(ar->f, "TODO");
|
||||
fprintf(ar->f, "}");
|
||||
} else if (type_entry->id == TypeTableEntryIdOpaque) {
|
||||
if (buf_eql_buf(&type_entry->name, name)) {
|
||||
fprintf(ar->f, "@OpaqueType()");
|
||||
} else {
|
||||
fprintf(ar->f, "%s", buf_ptr(&type_entry->name));
|
||||
}
|
||||
} else {
|
||||
fprintf(ar->f, "%s", buf_ptr(&type_entry->name));
|
||||
}
|
||||
@ -1047,15 +1037,6 @@ static void ast_render_tld_var(AstRender *ar, Buf *name, TldVar *tld_var) {
|
||||
fprintf(ar->f, ";\n");
|
||||
}
|
||||
|
||||
static void ast_render_tld_typedef(AstRender *ar, Buf *name, TldTypeDef *tld_typedef) {
|
||||
TypeTableEntry *type_entry = tld_typedef->type_entry;
|
||||
TypeTableEntry *canon_type = get_underlying_type(type_entry);
|
||||
|
||||
fprintf(ar->f, "pub type ");
|
||||
print_symbol(ar, name);
|
||||
fprintf(ar->f, " = %s;\n", buf_ptr(&canon_type->name));
|
||||
}
|
||||
|
||||
void ast_render_decls(FILE *f, int indent_size, ImportTableEntry *import) {
|
||||
AstRender ar = {0};
|
||||
ar.f = f;
|
||||
@ -1087,9 +1068,6 @@ void ast_render_decls(FILE *f, int indent_size, ImportTableEntry *import) {
|
||||
case TldIdContainer:
|
||||
fprintf(stdout, "container\n");
|
||||
break;
|
||||
case TldIdTypeDef:
|
||||
ast_render_tld_typedef(&ar, entry->key, (TldTypeDef *)tld);
|
||||
break;
|
||||
case TldIdCompTime:
|
||||
fprintf(stdout, "comptime\n");
|
||||
break;
|
||||
|
174
src/codegen.cpp
174
src/codegen.cpp
@ -649,12 +649,9 @@ static void add_bounds_check(CodeGen *g, LLVMValueRef target_val,
|
||||
LLVMPositionBuilderAtEnd(g->builder, ok_block);
|
||||
}
|
||||
|
||||
static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_debug_safety, TypeTableEntry *actual_type_non_canon,
|
||||
TypeTableEntry *wanted_type_non_canon, LLVMValueRef expr_val)
|
||||
static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_debug_safety, TypeTableEntry *actual_type,
|
||||
TypeTableEntry *wanted_type, LLVMValueRef expr_val)
|
||||
{
|
||||
TypeTableEntry *actual_type = get_underlying_type(actual_type_non_canon);
|
||||
TypeTableEntry *wanted_type = get_underlying_type(wanted_type_non_canon);
|
||||
|
||||
assert(actual_type->id == wanted_type->id);
|
||||
|
||||
uint64_t actual_bits;
|
||||
@ -852,7 +849,7 @@ static LLVMValueRef gen_struct_memcpy(CodeGen *g, LLVMValueRef src, LLVMValueRef
|
||||
static LLVMValueRef gen_assign_raw(CodeGen *g, LLVMValueRef ptr, TypeTableEntry *ptr_type,
|
||||
LLVMValueRef value)
|
||||
{
|
||||
TypeTableEntry *child_type = get_underlying_type(ptr_type->data.pointer.child_type);
|
||||
TypeTableEntry *child_type = ptr_type->data.pointer.child_type;
|
||||
|
||||
if (!type_has_bits(child_type))
|
||||
return nullptr;
|
||||
@ -1111,7 +1108,7 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
|
||||
IrInstruction *op2 = bin_op_instruction->op2;
|
||||
|
||||
assert(op1->value.type == op2->value.type);
|
||||
TypeTableEntry *canon_type = get_underlying_type(op1->value.type);
|
||||
TypeTableEntry *type_entry = op1->value.type;
|
||||
|
||||
bool want_debug_safety = bin_op_instruction->safety_check_on &&
|
||||
ir_want_debug_safety(g, &bin_op_instruction->base);
|
||||
@ -1133,22 +1130,22 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
|
||||
case IrBinOpCmpGreaterThan:
|
||||
case IrBinOpCmpLessOrEq:
|
||||
case IrBinOpCmpGreaterOrEq:
|
||||
if (canon_type->id == TypeTableEntryIdFloat) {
|
||||
if (type_entry->id == TypeTableEntryIdFloat) {
|
||||
LLVMRealPredicate pred = cmp_op_to_real_predicate(op_id);
|
||||
return LLVMBuildFCmp(g->builder, pred, op1_value, op2_value, "");
|
||||
} else if (canon_type->id == TypeTableEntryIdInt) {
|
||||
LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, canon_type->data.integral.is_signed);
|
||||
} else if (type_entry->id == TypeTableEntryIdInt) {
|
||||
LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, type_entry->data.integral.is_signed);
|
||||
return LLVMBuildICmp(g->builder, pred, op1_value, op2_value, "");
|
||||
} else if (canon_type->id == TypeTableEntryIdEnum) {
|
||||
if (canon_type->data.enumeration.gen_field_count == 0) {
|
||||
} else if (type_entry->id == TypeTableEntryIdEnum) {
|
||||
if (type_entry->data.enumeration.gen_field_count == 0) {
|
||||
LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, false);
|
||||
return LLVMBuildICmp(g->builder, pred, op1_value, op2_value, "");
|
||||
} else {
|
||||
zig_unreachable();
|
||||
}
|
||||
} else if (canon_type->id == TypeTableEntryIdPureError ||
|
||||
canon_type->id == TypeTableEntryIdPointer ||
|
||||
canon_type->id == TypeTableEntryIdBool)
|
||||
} else if (type_entry->id == TypeTableEntryIdPureError ||
|
||||
type_entry->id == TypeTableEntryIdPointer ||
|
||||
type_entry->id == TypeTableEntryIdBool)
|
||||
{
|
||||
LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, false);
|
||||
return LLVMBuildICmp(g->builder, pred, op1_value, op2_value, "");
|
||||
@ -1157,15 +1154,15 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
|
||||
}
|
||||
case IrBinOpAdd:
|
||||
case IrBinOpAddWrap:
|
||||
if (canon_type->id == TypeTableEntryIdFloat) {
|
||||
if (type_entry->id == TypeTableEntryIdFloat) {
|
||||
return LLVMBuildFAdd(g->builder, op1_value, op2_value, "");
|
||||
} else if (canon_type->id == TypeTableEntryIdInt) {
|
||||
} else if (type_entry->id == TypeTableEntryIdInt) {
|
||||
bool is_wrapping = (op_id == IrBinOpAddWrap);
|
||||
if (is_wrapping) {
|
||||
return LLVMBuildAdd(g->builder, op1_value, op2_value, "");
|
||||
} else if (want_debug_safety) {
|
||||
return gen_overflow_op(g, canon_type, AddSubMulAdd, op1_value, op2_value);
|
||||
} else if (canon_type->data.integral.is_signed) {
|
||||
return gen_overflow_op(g, type_entry, AddSubMulAdd, op1_value, op2_value);
|
||||
} else if (type_entry->data.integral.is_signed) {
|
||||
return LLVMBuildNSWAdd(g->builder, op1_value, op2_value, "");
|
||||
} else {
|
||||
return LLVMBuildNUWAdd(g->builder, op1_value, op2_value, "");
|
||||
@ -1182,36 +1179,36 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
|
||||
case IrBinOpBitShiftLeft:
|
||||
case IrBinOpBitShiftLeftWrap:
|
||||
{
|
||||
assert(canon_type->id == TypeTableEntryIdInt);
|
||||
assert(type_entry->id == TypeTableEntryIdInt);
|
||||
bool is_wrapping = (op_id == IrBinOpBitShiftLeftWrap);
|
||||
if (is_wrapping) {
|
||||
return LLVMBuildShl(g->builder, op1_value, op2_value, "");
|
||||
} else if (want_debug_safety) {
|
||||
return gen_overflow_shl_op(g, canon_type, op1_value, op2_value);
|
||||
} else if (canon_type->data.integral.is_signed) {
|
||||
return gen_overflow_shl_op(g, type_entry, op1_value, op2_value);
|
||||
} else if (type_entry->data.integral.is_signed) {
|
||||
return ZigLLVMBuildNSWShl(g->builder, op1_value, op2_value, "");
|
||||
} else {
|
||||
return ZigLLVMBuildNUWShl(g->builder, op1_value, op2_value, "");
|
||||
}
|
||||
}
|
||||
case IrBinOpBitShiftRight:
|
||||
assert(canon_type->id == TypeTableEntryIdInt);
|
||||
if (canon_type->data.integral.is_signed) {
|
||||
assert(type_entry->id == TypeTableEntryIdInt);
|
||||
if (type_entry->data.integral.is_signed) {
|
||||
return LLVMBuildAShr(g->builder, op1_value, op2_value, "");
|
||||
} else {
|
||||
return LLVMBuildLShr(g->builder, op1_value, op2_value, "");
|
||||
}
|
||||
case IrBinOpSub:
|
||||
case IrBinOpSubWrap:
|
||||
if (canon_type->id == TypeTableEntryIdFloat) {
|
||||
if (type_entry->id == TypeTableEntryIdFloat) {
|
||||
return LLVMBuildFSub(g->builder, op1_value, op2_value, "");
|
||||
} else if (canon_type->id == TypeTableEntryIdInt) {
|
||||
} else if (type_entry->id == TypeTableEntryIdInt) {
|
||||
bool is_wrapping = (op_id == IrBinOpSubWrap);
|
||||
if (is_wrapping) {
|
||||
return LLVMBuildSub(g->builder, op1_value, op2_value, "");
|
||||
} else if (want_debug_safety) {
|
||||
return gen_overflow_op(g, canon_type, AddSubMulSub, op1_value, op2_value);
|
||||
} else if (canon_type->data.integral.is_signed) {
|
||||
return gen_overflow_op(g, type_entry, AddSubMulSub, op1_value, op2_value);
|
||||
} else if (type_entry->data.integral.is_signed) {
|
||||
return LLVMBuildNSWSub(g->builder, op1_value, op2_value, "");
|
||||
} else {
|
||||
return LLVMBuildNUWSub(g->builder, op1_value, op2_value, "");
|
||||
@ -1221,15 +1218,15 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
|
||||
}
|
||||
case IrBinOpMult:
|
||||
case IrBinOpMultWrap:
|
||||
if (canon_type->id == TypeTableEntryIdFloat) {
|
||||
if (type_entry->id == TypeTableEntryIdFloat) {
|
||||
return LLVMBuildFMul(g->builder, op1_value, op2_value, "");
|
||||
} else if (canon_type->id == TypeTableEntryIdInt) {
|
||||
} else if (type_entry->id == TypeTableEntryIdInt) {
|
||||
bool is_wrapping = (op_id == IrBinOpMultWrap);
|
||||
if (is_wrapping) {
|
||||
return LLVMBuildMul(g->builder, op1_value, op2_value, "");
|
||||
} else if (want_debug_safety) {
|
||||
return gen_overflow_op(g, canon_type, AddSubMulMul, op1_value, op2_value);
|
||||
} else if (canon_type->data.integral.is_signed) {
|
||||
return gen_overflow_op(g, type_entry, AddSubMulMul, op1_value, op2_value);
|
||||
} else if (type_entry->data.integral.is_signed) {
|
||||
return LLVMBuildNSWMul(g->builder, op1_value, op2_value, "");
|
||||
} else {
|
||||
return LLVMBuildNUWMul(g->builder, op1_value, op2_value, "");
|
||||
@ -1238,9 +1235,9 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
|
||||
zig_unreachable();
|
||||
}
|
||||
case IrBinOpDiv:
|
||||
return gen_div(g, want_debug_safety, op1_value, op2_value, canon_type, false);
|
||||
return gen_div(g, want_debug_safety, op1_value, op2_value, type_entry, false);
|
||||
case IrBinOpRem:
|
||||
return gen_rem(g, want_debug_safety, op1_value, op2_value, canon_type);
|
||||
return gen_rem(g, want_debug_safety, op1_value, op2_value, type_entry);
|
||||
}
|
||||
zig_unreachable();
|
||||
}
|
||||
@ -1644,7 +1641,7 @@ static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, Ir
|
||||
LLVMValueRef value = ir_llvm_value(g, instruction->value);
|
||||
|
||||
assert(instruction->ptr->value.type->id == TypeTableEntryIdPointer);
|
||||
TypeTableEntry *ptr_type = get_underlying_type(instruction->ptr->value.type);
|
||||
TypeTableEntry *ptr_type = instruction->ptr->value.type;
|
||||
|
||||
gen_assign_raw(g, ptr, ptr_type, value);
|
||||
|
||||
@ -1685,9 +1682,9 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI
|
||||
if (array_ptr_type->data.pointer.unaligned_bit_count != 0) {
|
||||
return array_ptr_ptr;
|
||||
}
|
||||
TypeTableEntry *canon_child_type = get_underlying_type(array_type->data.array.child_type);
|
||||
if (canon_child_type->id == TypeTableEntryIdStruct &&
|
||||
canon_child_type->data.structure.layout == ContainerLayoutPacked)
|
||||
TypeTableEntry *child_type = array_type->data.array.child_type;
|
||||
if (child_type->id == TypeTableEntryIdStruct &&
|
||||
child_type->data.structure.layout == ContainerLayoutPacked)
|
||||
{
|
||||
size_t unaligned_bit_count = instruction->base.value.type->data.pointer.unaligned_bit_count;
|
||||
if (unaligned_bit_count != 0) {
|
||||
@ -1701,7 +1698,7 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI
|
||||
byte_offset
|
||||
};
|
||||
LLVMValueRef elem_byte_ptr = LLVMBuildInBoundsGEP(g->builder, u8_array_ptr, indices, 1, "");
|
||||
return LLVMBuildBitCast(g->builder, elem_byte_ptr, LLVMPointerType(canon_child_type->type_ref, 0), "");
|
||||
return LLVMBuildBitCast(g->builder, elem_byte_ptr, LLVMPointerType(child_type->type_ref, 0), "");
|
||||
}
|
||||
}
|
||||
LLVMValueRef indices[] = {
|
||||
@ -2206,8 +2203,8 @@ static LLVMValueRef ir_render_div_exact(CodeGen *g, IrExecutable *executable, Ir
|
||||
|
||||
static LLVMValueRef ir_render_truncate(CodeGen *g, IrExecutable *executable, IrInstructionTruncate *instruction) {
|
||||
LLVMValueRef target_val = ir_llvm_value(g, instruction->target);
|
||||
TypeTableEntry *dest_type = get_underlying_type(instruction->base.value.type);
|
||||
TypeTableEntry *src_type = get_underlying_type(instruction->target->value.type);
|
||||
TypeTableEntry *dest_type = instruction->base.value.type;
|
||||
TypeTableEntry *src_type = instruction->target->value.type;
|
||||
if (dest_type == src_type) {
|
||||
// no-op
|
||||
return target_val;
|
||||
@ -2228,7 +2225,7 @@ static LLVMValueRef ir_render_memset(CodeGen *g, IrExecutable *executable, IrIns
|
||||
|
||||
LLVMValueRef dest_ptr_casted = LLVMBuildBitCast(g->builder, dest_ptr, ptr_u8, "");
|
||||
|
||||
TypeTableEntry *ptr_type = get_underlying_type(instruction->dest_ptr->value.type);
|
||||
TypeTableEntry *ptr_type = instruction->dest_ptr->value.type;
|
||||
assert(ptr_type->id == TypeTableEntryIdPointer);
|
||||
|
||||
LLVMValueRef is_volatile = ptr_type->data.pointer.is_volatile ?
|
||||
@ -2256,8 +2253,8 @@ static LLVMValueRef ir_render_memcpy(CodeGen *g, IrExecutable *executable, IrIns
|
||||
LLVMValueRef dest_ptr_casted = LLVMBuildBitCast(g->builder, dest_ptr, ptr_u8, "");
|
||||
LLVMValueRef src_ptr_casted = LLVMBuildBitCast(g->builder, src_ptr, ptr_u8, "");
|
||||
|
||||
TypeTableEntry *dest_ptr_type = get_underlying_type(instruction->dest_ptr->value.type);
|
||||
TypeTableEntry *src_ptr_type = get_underlying_type(instruction->src_ptr->value.type);
|
||||
TypeTableEntry *dest_ptr_type = instruction->dest_ptr->value.type;
|
||||
TypeTableEntry *src_ptr_type = instruction->src_ptr->value.type;
|
||||
|
||||
assert(dest_ptr_type->id == TypeTableEntryIdPointer);
|
||||
assert(src_ptr_type->id == TypeTableEntryIdPointer);
|
||||
@ -2407,7 +2404,7 @@ static LLVMValueRef ir_render_frame_address(CodeGen *g, IrExecutable *executable
|
||||
}
|
||||
|
||||
static LLVMValueRef render_shl_with_overflow(CodeGen *g, IrInstructionOverflowOp *instruction) {
|
||||
TypeTableEntry *int_type = get_underlying_type(instruction->result_ptr_type);
|
||||
TypeTableEntry *int_type = instruction->result_ptr_type;
|
||||
assert(int_type->id == TypeTableEntryIdInt);
|
||||
|
||||
LLVMValueRef op1 = ir_llvm_value(g, instruction->op1);
|
||||
@ -2444,7 +2441,7 @@ static LLVMValueRef ir_render_overflow_op(CodeGen *g, IrExecutable *executable,
|
||||
return render_shl_with_overflow(g, instruction);
|
||||
}
|
||||
|
||||
TypeTableEntry *int_type = get_underlying_type(instruction->result_ptr_type);
|
||||
TypeTableEntry *int_type = instruction->result_ptr_type;
|
||||
assert(int_type->id == TypeTableEntryIdInt);
|
||||
|
||||
LLVMValueRef fn_val = get_int_overflow_fn(g, int_type, add_sub_mul);
|
||||
@ -2467,8 +2464,8 @@ static LLVMValueRef ir_render_overflow_op(CodeGen *g, IrExecutable *executable,
|
||||
}
|
||||
|
||||
static LLVMValueRef ir_render_test_err(CodeGen *g, IrExecutable *executable, IrInstructionTestErr *instruction) {
|
||||
TypeTableEntry *err_union_type = get_underlying_type(instruction->value->value.type);
|
||||
TypeTableEntry *child_type = get_underlying_type(err_union_type->data.error.child_type);
|
||||
TypeTableEntry *err_union_type = instruction->value->value.type;
|
||||
TypeTableEntry *child_type = err_union_type->data.error.child_type;
|
||||
LLVMValueRef err_union_handle = ir_llvm_value(g, instruction->value);
|
||||
|
||||
LLVMValueRef err_val;
|
||||
@ -2484,11 +2481,11 @@ static LLVMValueRef ir_render_test_err(CodeGen *g, IrExecutable *executable, IrI
|
||||
}
|
||||
|
||||
static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executable, IrInstructionUnwrapErrCode *instruction) {
|
||||
TypeTableEntry *ptr_type = get_underlying_type(instruction->value->value.type);
|
||||
TypeTableEntry *ptr_type = instruction->value->value.type;
|
||||
assert(ptr_type->id == TypeTableEntryIdPointer);
|
||||
bool is_volatile = ptr_type->data.pointer.is_volatile;
|
||||
TypeTableEntry *err_union_type = get_underlying_type(ptr_type->data.pointer.child_type);
|
||||
TypeTableEntry *child_type = get_underlying_type(err_union_type->data.error.child_type);
|
||||
TypeTableEntry *err_union_type = ptr_type->data.pointer.child_type;
|
||||
TypeTableEntry *child_type = err_union_type->data.error.child_type;
|
||||
LLVMValueRef err_union_ptr = ir_llvm_value(g, instruction->value);
|
||||
LLVMValueRef err_union_handle = get_handle_value(g, err_union_ptr, err_union_type, is_volatile);
|
||||
|
||||
@ -2501,11 +2498,11 @@ static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executab
|
||||
}
|
||||
|
||||
static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *executable, IrInstructionUnwrapErrPayload *instruction) {
|
||||
TypeTableEntry *ptr_type = get_underlying_type(instruction->value->value.type);
|
||||
TypeTableEntry *ptr_type = instruction->value->value.type;
|
||||
assert(ptr_type->id == TypeTableEntryIdPointer);
|
||||
bool is_volatile = ptr_type->data.pointer.is_volatile;
|
||||
TypeTableEntry *err_union_type = get_underlying_type(ptr_type->data.pointer.child_type);
|
||||
TypeTableEntry *child_type = get_underlying_type(err_union_type->data.error.child_type);
|
||||
TypeTableEntry *err_union_type = ptr_type->data.pointer.child_type;
|
||||
TypeTableEntry *child_type = err_union_type->data.error.child_type;
|
||||
LLVMValueRef err_union_ptr = ir_llvm_value(g, instruction->value);
|
||||
LLVMValueRef err_union_handle = get_handle_value(g, err_union_ptr, err_union_type, is_volatile);
|
||||
|
||||
@ -2941,9 +2938,9 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con
|
||||
break;
|
||||
}
|
||||
|
||||
TypeTableEntry *canon_type = get_underlying_type(const_val->type);
|
||||
assert(!canon_type->zero_bits);
|
||||
switch (canon_type->id) {
|
||||
TypeTableEntry *type_entry = const_val->type;
|
||||
assert(!type_entry->zero_bits);
|
||||
switch (type_entry->id) {
|
||||
case TypeTableEntryIdInvalid:
|
||||
case TypeTableEntryIdVar:
|
||||
case TypeTableEntryIdMetaType:
|
||||
@ -2956,12 +2953,12 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con
|
||||
case TypeTableEntryIdPureError:
|
||||
case TypeTableEntryIdEnum:
|
||||
case TypeTableEntryIdEnumTag:
|
||||
case TypeTableEntryIdTypeDecl:
|
||||
case TypeTableEntryIdNamespace:
|
||||
case TypeTableEntryIdBlock:
|
||||
case TypeTableEntryIdBoundFn:
|
||||
case TypeTableEntryIdArgTuple:
|
||||
case TypeTableEntryIdVoid:
|
||||
case TypeTableEntryIdOpaque:
|
||||
zig_unreachable();
|
||||
case TypeTableEntryIdBool:
|
||||
return LLVMConstInt(big_int_type_ref, const_val->data.x_bool ? 1 : 0, false);
|
||||
@ -2975,7 +2972,7 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con
|
||||
{
|
||||
LLVMValueRef float_val = gen_const_val(g, const_val);
|
||||
LLVMValueRef int_val = LLVMConstFPToUI(float_val,
|
||||
LLVMIntType((unsigned)canon_type->data.floating.bit_count));
|
||||
LLVMIntType((unsigned)type_entry->data.floating.bit_count));
|
||||
return LLVMConstZExt(int_val, big_int_type_ref);
|
||||
}
|
||||
case TypeTableEntryIdPointer:
|
||||
@ -2992,11 +2989,11 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con
|
||||
zig_panic("TODO bit pack a union");
|
||||
case TypeTableEntryIdStruct:
|
||||
{
|
||||
assert(canon_type->data.structure.layout == ContainerLayoutPacked);
|
||||
assert(type_entry->data.structure.layout == ContainerLayoutPacked);
|
||||
|
||||
LLVMValueRef val = LLVMConstInt(big_int_type_ref, 0, false);
|
||||
for (size_t i = 0; i < canon_type->data.structure.src_field_count; i += 1) {
|
||||
TypeStructField *field = &canon_type->data.structure.fields[i];
|
||||
for (size_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) {
|
||||
TypeStructField *field = &type_entry->data.structure.fields[i];
|
||||
if (field->gen_index == SIZE_MAX) {
|
||||
continue;
|
||||
}
|
||||
@ -3012,37 +3009,35 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con
|
||||
}
|
||||
|
||||
static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
|
||||
TypeTableEntry *canon_type = get_underlying_type(const_val->type);
|
||||
assert(!canon_type->zero_bits);
|
||||
TypeTableEntry *type_entry = const_val->type;
|
||||
assert(!type_entry->zero_bits);
|
||||
|
||||
switch (const_val->special) {
|
||||
case ConstValSpecialRuntime:
|
||||
zig_unreachable();
|
||||
case ConstValSpecialUndef:
|
||||
return LLVMGetUndef(canon_type->type_ref);
|
||||
return LLVMGetUndef(type_entry->type_ref);
|
||||
case ConstValSpecialStatic:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (canon_type->id) {
|
||||
case TypeTableEntryIdTypeDecl:
|
||||
zig_unreachable();
|
||||
switch (type_entry->id) {
|
||||
case TypeTableEntryIdInt:
|
||||
case TypeTableEntryIdEnumTag:
|
||||
return LLVMConstInt(canon_type->type_ref, bignum_to_twos_complement(&const_val->data.x_bignum), false);
|
||||
return LLVMConstInt(type_entry->type_ref, bignum_to_twos_complement(&const_val->data.x_bignum), false);
|
||||
case TypeTableEntryIdPureError:
|
||||
assert(const_val->data.x_pure_err);
|
||||
return LLVMConstInt(g->builtin_types.entry_pure_error->type_ref,
|
||||
const_val->data.x_pure_err->value, false);
|
||||
case TypeTableEntryIdFloat:
|
||||
if (const_val->data.x_bignum.kind == BigNumKindFloat) {
|
||||
return LLVMConstReal(canon_type->type_ref, const_val->data.x_bignum.data.x_float);
|
||||
return LLVMConstReal(type_entry->type_ref, const_val->data.x_bignum.data.x_float);
|
||||
} else {
|
||||
double x = (double)const_val->data.x_bignum.data.x_uint;
|
||||
if (const_val->data.x_bignum.is_negative) {
|
||||
x = -x;
|
||||
}
|
||||
return LLVMConstReal(canon_type->type_ref, x);
|
||||
return LLVMConstReal(type_entry->type_ref, x);
|
||||
}
|
||||
case TypeTableEntryIdBool:
|
||||
if (const_val->data.x_bool) {
|
||||
@ -3052,7 +3047,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
|
||||
}
|
||||
case TypeTableEntryIdMaybe:
|
||||
{
|
||||
TypeTableEntry *child_type = canon_type->data.maybe.child_type;
|
||||
TypeTableEntry *child_type = type_entry->data.maybe.child_type;
|
||||
if (child_type->zero_bits) {
|
||||
return LLVMConstInt(LLVMInt1Type(), const_val->data.x_maybe ? 1 : 0, false);
|
||||
} else if (child_type->id == TypeTableEntryIdPointer ||
|
||||
@ -3082,12 +3077,12 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
|
||||
}
|
||||
case TypeTableEntryIdStruct:
|
||||
{
|
||||
LLVMValueRef *fields = allocate<LLVMValueRef>(canon_type->data.structure.gen_field_count);
|
||||
size_t src_field_count = canon_type->data.structure.src_field_count;
|
||||
if (canon_type->data.structure.layout == ContainerLayoutPacked) {
|
||||
LLVMValueRef *fields = allocate<LLVMValueRef>(type_entry->data.structure.gen_field_count);
|
||||
size_t src_field_count = type_entry->data.structure.src_field_count;
|
||||
if (type_entry->data.structure.layout == ContainerLayoutPacked) {
|
||||
size_t src_field_index = 0;
|
||||
while (src_field_index < src_field_count) {
|
||||
TypeStructField *type_struct_field = &canon_type->data.structure.fields[src_field_index];
|
||||
TypeStructField *type_struct_field = &type_entry->data.structure.fields[src_field_index];
|
||||
if (type_struct_field->gen_index == SIZE_MAX) {
|
||||
src_field_index += 1;
|
||||
continue;
|
||||
@ -3095,7 +3090,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
|
||||
|
||||
size_t src_field_index_end = src_field_index + 1;
|
||||
for (; src_field_index_end < src_field_count; src_field_index_end += 1) {
|
||||
TypeStructField *it_field = &canon_type->data.structure.fields[src_field_index_end];
|
||||
TypeStructField *it_field = &type_entry->data.structure.fields[src_field_index_end];
|
||||
if (it_field->gen_index != type_struct_field->gen_index)
|
||||
break;
|
||||
}
|
||||
@ -3104,11 +3099,11 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
|
||||
fields[type_struct_field->gen_index] =
|
||||
gen_const_val(g, &const_val->data.x_struct.fields[src_field_index]);
|
||||
} else {
|
||||
LLVMTypeRef big_int_type_ref = LLVMStructGetTypeAtIndex(canon_type->type_ref,
|
||||
LLVMTypeRef big_int_type_ref = LLVMStructGetTypeAtIndex(type_entry->type_ref,
|
||||
(unsigned)type_struct_field->gen_index);
|
||||
LLVMValueRef val = LLVMConstInt(big_int_type_ref, 0, false);
|
||||
for (size_t i = src_field_index; i < src_field_index_end; i += 1) {
|
||||
TypeStructField *it_field = &canon_type->data.structure.fields[i];
|
||||
TypeStructField *it_field = &type_entry->data.structure.fields[i];
|
||||
if (it_field->gen_index == SIZE_MAX) {
|
||||
continue;
|
||||
}
|
||||
@ -3126,14 +3121,14 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
|
||||
}
|
||||
} else {
|
||||
for (uint32_t i = 0; i < src_field_count; i += 1) {
|
||||
TypeStructField *type_struct_field = &canon_type->data.structure.fields[i];
|
||||
TypeStructField *type_struct_field = &type_entry->data.structure.fields[i];
|
||||
if (type_struct_field->gen_index == SIZE_MAX) {
|
||||
continue;
|
||||
}
|
||||
fields[type_struct_field->gen_index] = gen_const_val(g, &const_val->data.x_struct.fields[i]);
|
||||
}
|
||||
}
|
||||
return LLVMConstNamedStruct(canon_type->type_ref, fields, canon_type->data.structure.gen_field_count);
|
||||
return LLVMConstNamedStruct(type_entry->type_ref, fields, type_entry->data.structure.gen_field_count);
|
||||
}
|
||||
case TypeTableEntryIdUnion:
|
||||
{
|
||||
@ -3141,7 +3136,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
|
||||
}
|
||||
case TypeTableEntryIdArray:
|
||||
{
|
||||
uint64_t len = canon_type->data.array.len;
|
||||
uint64_t len = type_entry->data.array.len;
|
||||
LLVMValueRef *values = allocate<LLVMValueRef>(len);
|
||||
for (uint64_t i = 0; i < len; i += 1) {
|
||||
ConstExprValue *elem_value = &const_val->data.x_array.elements[i];
|
||||
@ -3151,13 +3146,13 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
|
||||
}
|
||||
case TypeTableEntryIdEnum:
|
||||
{
|
||||
LLVMTypeRef tag_type_ref = canon_type->data.enumeration.tag_type->type_ref;
|
||||
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);
|
||||
if (canon_type->data.enumeration.gen_field_count == 0) {
|
||||
if (type_entry->data.enumeration.gen_field_count == 0) {
|
||||
return tag_value;
|
||||
} else {
|
||||
TypeTableEntry *union_type = canon_type->data.enumeration.union_type;
|
||||
TypeEnumField *enum_field = &canon_type->data.enumeration.fields[const_val->data.x_enum.tag];
|
||||
TypeTableEntry *union_type = type_entry->data.enumeration.union_type;
|
||||
TypeEnumField *enum_field = &type_entry->data.enumeration.fields[const_val->data.x_enum.tag];
|
||||
assert(enum_field->value == const_val->data.x_enum.tag);
|
||||
LLVMValueRef union_value;
|
||||
if (type_has_bits(enum_field->type_entry)) {
|
||||
@ -3261,7 +3256,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
|
||||
}
|
||||
case TypeTableEntryIdErrorUnion:
|
||||
{
|
||||
TypeTableEntry *child_type = canon_type->data.error.child_type;
|
||||
TypeTableEntry *child_type = type_entry->data.error.child_type;
|
||||
if (!type_has_bits(child_type)) {
|
||||
uint64_t value = const_val->data.x_err_union.err ? const_val->data.x_err_union.err->value : 0;
|
||||
return LLVMConstInt(g->err_tag_type->type_ref, value, false);
|
||||
@ -3296,6 +3291,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) {
|
||||
case TypeTableEntryIdBoundFn:
|
||||
case TypeTableEntryIdVar:
|
||||
case TypeTableEntryIdArgTuple:
|
||||
case TypeTableEntryIdOpaque:
|
||||
zig_unreachable();
|
||||
|
||||
}
|
||||
@ -4107,7 +4103,7 @@ static void define_builtin_types(CodeGen *g) {
|
||||
g->builtin_types.entry_i64 = get_int_type(g, true, 64);
|
||||
|
||||
{
|
||||
g->builtin_types.entry_c_void = get_typedecl_type(g, "c_void", g->builtin_types.entry_u8);
|
||||
g->builtin_types.entry_c_void = get_opaque_type(g, nullptr, nullptr, "c_void");
|
||||
g->primitive_type_table.put(&g->builtin_types.entry_c_void->name, g->builtin_types.entry_c_void);
|
||||
}
|
||||
|
||||
@ -4747,6 +4743,7 @@ static void get_c_type(CodeGen *g, TypeTableEntry *type_entry, Buf *out_buf) {
|
||||
zig_unreachable();
|
||||
}
|
||||
}
|
||||
case TypeTableEntryIdOpaque:
|
||||
case TypeTableEntryIdArray:
|
||||
case TypeTableEntryIdStruct:
|
||||
case TypeTableEntryIdErrorUnion:
|
||||
@ -4754,7 +4751,6 @@ static void get_c_type(CodeGen *g, TypeTableEntry *type_entry, Buf *out_buf) {
|
||||
case TypeTableEntryIdEnum:
|
||||
case TypeTableEntryIdUnion:
|
||||
case TypeTableEntryIdFn:
|
||||
case TypeTableEntryIdTypeDecl:
|
||||
case TypeTableEntryIdEnumTag:
|
||||
zig_panic("TODO implement get_c_type for more types");
|
||||
case TypeTableEntryIdInvalid:
|
||||
|
377
src/ir.cpp
377
src/ir.cpp
@ -5323,11 +5323,6 @@ static IrInstruction *ir_gen_continue(IrBuilder *irb, Scope *scope, AstNode *nod
|
||||
return ir_build_br(irb, scope, node, dest_block, is_comptime);
|
||||
}
|
||||
|
||||
static IrInstruction *ir_gen_type_literal(IrBuilder *irb, Scope *scope, AstNode *node) {
|
||||
assert(node->type == NodeTypeTypeLiteral);
|
||||
return ir_build_const_type(irb, scope, node, irb->codegen->builtin_types.entry_type);
|
||||
}
|
||||
|
||||
static IrInstruction *ir_gen_error_type(IrBuilder *irb, Scope *scope, AstNode *node) {
|
||||
assert(node->type == NodeTypeErrorType);
|
||||
return ir_build_const_type(irb, scope, node, irb->codegen->builtin_types.entry_pure_error);
|
||||
@ -5600,8 +5595,6 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
|
||||
return ir_lval_wrap(irb, scope, ir_gen_goto(irb, scope, node), lval);
|
||||
case NodeTypeCompTime:
|
||||
return ir_gen_comptime(irb, scope, node, lval);
|
||||
case NodeTypeTypeLiteral:
|
||||
return ir_lval_wrap(irb, scope, ir_gen_type_literal(irb, scope, node), lval);
|
||||
case NodeTypeErrorType:
|
||||
return ir_lval_wrap(irb, scope, ir_gen_error_type(irb, scope, node), lval);
|
||||
case NodeTypeBreak:
|
||||
@ -5628,8 +5621,6 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
|
||||
zig_panic("TODO IR gen NodeTypeFnDecl");
|
||||
case NodeTypeErrorValueDecl:
|
||||
zig_panic("TODO IR gen NodeTypeErrorValueDecl");
|
||||
case NodeTypeTypeDecl:
|
||||
zig_panic("TODO IR gen NodeTypeTypeDecl");
|
||||
case NodeTypeTestDecl:
|
||||
zig_panic("TODO IR gen NodeTypeTestDecl");
|
||||
}
|
||||
@ -5753,13 +5744,6 @@ static ErrorMsg *ir_add_error(IrAnalyze *ira, IrInstruction *source_instruction,
|
||||
return ir_add_error_node(ira, source_instruction->source_node, msg);
|
||||
}
|
||||
|
||||
static void ir_add_typedef_err_note(IrAnalyze *ira, ErrorMsg *msg, TypeTableEntry *type_entry) {
|
||||
if (type_entry->id == TypeTableEntryIdTypeDecl) {
|
||||
// requires tracking source_node in the typedecl type
|
||||
zig_panic("TODO add error note about typedecls");
|
||||
}
|
||||
}
|
||||
|
||||
static IrInstruction *ir_exec_const_result(CodeGen *codegen, IrExecutable *exec) {
|
||||
IrBasicBlock *bb = exec->basic_block_list.at(0);
|
||||
for (size_t i = 0; i < bb->instruction_list.length; i += 1) {
|
||||
@ -5791,27 +5775,25 @@ static bool ir_emit_global_runtime_side_effect(IrAnalyze *ira, IrInstruction *so
|
||||
}
|
||||
|
||||
static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruction, TypeTableEntry *other_type) {
|
||||
TypeTableEntry *other_type_underlying = get_underlying_type(other_type);
|
||||
|
||||
if (type_is_invalid(other_type_underlying)) {
|
||||
if (type_is_invalid(other_type)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ConstExprValue *const_val = &instruction->value;
|
||||
assert(const_val->special != ConstValSpecialRuntime);
|
||||
if (other_type_underlying->id == TypeTableEntryIdFloat) {
|
||||
if (other_type->id == TypeTableEntryIdFloat) {
|
||||
return true;
|
||||
} else if (other_type_underlying->id == TypeTableEntryIdInt &&
|
||||
} else if (other_type->id == TypeTableEntryIdInt &&
|
||||
const_val->data.x_bignum.kind == BigNumKindInt)
|
||||
{
|
||||
if (bignum_fits_in_bits(&const_val->data.x_bignum, other_type_underlying->data.integral.bit_count,
|
||||
other_type_underlying->data.integral.is_signed))
|
||||
if (bignum_fits_in_bits(&const_val->data.x_bignum, other_type->data.integral.bit_count,
|
||||
other_type->data.integral.is_signed))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
} else if ((other_type_underlying->id == TypeTableEntryIdNumLitFloat &&
|
||||
} else if ((other_type->id == TypeTableEntryIdNumLitFloat &&
|
||||
const_val->data.x_bignum.kind == BigNumKindFloat) ||
|
||||
(other_type_underlying->id == TypeTableEntryIdNumLitInt &&
|
||||
(other_type->id == TypeTableEntryIdNumLitInt &&
|
||||
const_val->data.x_bignum.kind == BigNumKindInt))
|
||||
{
|
||||
return true;
|
||||
@ -6890,12 +6872,9 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
|
||||
TypeTableEntry *wanted_type, IrInstruction *value)
|
||||
{
|
||||
TypeTableEntry *actual_type = value->value.type;
|
||||
TypeTableEntry *wanted_type_canon = get_underlying_type(wanted_type);
|
||||
TypeTableEntry *actual_type_canon = get_underlying_type(actual_type);
|
||||
|
||||
TypeTableEntry *usize_type = ira->codegen->builtin_types.entry_usize;
|
||||
|
||||
if (type_is_invalid(wanted_type_canon) || type_is_invalid(actual_type_canon)) {
|
||||
if (type_is_invalid(wanted_type) || type_is_invalid(actual_type)) {
|
||||
return ira->codegen->invalid_instruction;
|
||||
}
|
||||
|
||||
@ -6908,36 +6887,36 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
|
||||
}
|
||||
|
||||
// explicit cast from bool to int
|
||||
if (wanted_type_canon->id == TypeTableEntryIdInt &&
|
||||
actual_type_canon->id == TypeTableEntryIdBool)
|
||||
if (wanted_type->id == TypeTableEntryIdInt &&
|
||||
actual_type->id == TypeTableEntryIdBool)
|
||||
{
|
||||
return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpBoolToInt, false);
|
||||
}
|
||||
|
||||
// explicit cast from pointer to usize
|
||||
if (wanted_type_canon == usize_type && type_is_codegen_pointer(actual_type_canon)) {
|
||||
if (wanted_type == usize_type && type_is_codegen_pointer(actual_type)) {
|
||||
return ir_analyze_ptr_to_int(ira, source_instr, value, wanted_type);
|
||||
}
|
||||
|
||||
// explicit widening or shortening cast
|
||||
if ((wanted_type_canon->id == TypeTableEntryIdInt &&
|
||||
actual_type_canon->id == TypeTableEntryIdInt) ||
|
||||
(wanted_type_canon->id == TypeTableEntryIdFloat &&
|
||||
actual_type_canon->id == TypeTableEntryIdFloat))
|
||||
if ((wanted_type->id == TypeTableEntryIdInt &&
|
||||
actual_type->id == TypeTableEntryIdInt) ||
|
||||
(wanted_type->id == TypeTableEntryIdFloat &&
|
||||
actual_type->id == TypeTableEntryIdFloat))
|
||||
{
|
||||
return ir_analyze_widen_or_shorten(ira, source_instr, value, wanted_type);
|
||||
}
|
||||
|
||||
// explicit cast from int to float
|
||||
if (wanted_type_canon->id == TypeTableEntryIdFloat &&
|
||||
actual_type_canon->id == TypeTableEntryIdInt)
|
||||
if (wanted_type->id == TypeTableEntryIdFloat &&
|
||||
actual_type->id == TypeTableEntryIdInt)
|
||||
{
|
||||
return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpIntToFloat, false);
|
||||
}
|
||||
|
||||
// explicit cast from float to int
|
||||
if (wanted_type_canon->id == TypeTableEntryIdInt &&
|
||||
actual_type_canon->id == TypeTableEntryIdFloat)
|
||||
if (wanted_type->id == TypeTableEntryIdInt &&
|
||||
actual_type->id == TypeTableEntryIdFloat)
|
||||
{
|
||||
return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpFloatToInt, false);
|
||||
}
|
||||
@ -7070,17 +7049,17 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
|
||||
return ira->codegen->invalid_instruction;
|
||||
|
||||
return cast2;
|
||||
} else if (ir_num_lit_fits_in_other_type(ira, value, wanted_type_canon)) {
|
||||
} else if (ir_num_lit_fits_in_other_type(ira, value, wanted_type)) {
|
||||
CastOp op;
|
||||
if ((actual_type->id == TypeTableEntryIdNumLitFloat &&
|
||||
wanted_type_canon->id == TypeTableEntryIdFloat) ||
|
||||
wanted_type->id == TypeTableEntryIdFloat) ||
|
||||
(actual_type->id == TypeTableEntryIdNumLitInt &&
|
||||
wanted_type_canon->id == TypeTableEntryIdInt))
|
||||
wanted_type->id == TypeTableEntryIdInt))
|
||||
{
|
||||
op = CastOpNoop;
|
||||
} else if (wanted_type_canon->id == TypeTableEntryIdInt) {
|
||||
} else if (wanted_type->id == TypeTableEntryIdInt) {
|
||||
op = CastOpFloatToInt;
|
||||
} else if (wanted_type_canon->id == TypeTableEntryIdFloat) {
|
||||
} else if (wanted_type->id == TypeTableEntryIdFloat) {
|
||||
op = CastOpIntToFloat;
|
||||
} else {
|
||||
zig_unreachable();
|
||||
@ -7475,7 +7454,7 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp
|
||||
case TypeTableEntryIdPointer:
|
||||
case TypeTableEntryIdPureError:
|
||||
case TypeTableEntryIdFn:
|
||||
case TypeTableEntryIdTypeDecl:
|
||||
case TypeTableEntryIdOpaque:
|
||||
case TypeTableEntryIdNamespace:
|
||||
case TypeTableEntryIdBlock:
|
||||
case TypeTableEntryIdBoundFn:
|
||||
@ -7709,15 +7688,14 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
|
||||
TypeTableEntry *resolved_type = ir_resolve_peer_types(ira, bin_op_instruction->base.source_node, instructions, 2);
|
||||
if (type_is_invalid(resolved_type))
|
||||
return resolved_type;
|
||||
TypeTableEntry *canon_resolved_type = get_underlying_type(resolved_type);
|
||||
IrBinOp op_id = bin_op_instruction->op_id;
|
||||
|
||||
if (canon_resolved_type->id == TypeTableEntryIdInt ||
|
||||
canon_resolved_type->id == TypeTableEntryIdNumLitInt)
|
||||
if (resolved_type->id == TypeTableEntryIdInt ||
|
||||
resolved_type->id == TypeTableEntryIdNumLitInt)
|
||||
{
|
||||
// int
|
||||
} else if ((canon_resolved_type->id == TypeTableEntryIdFloat ||
|
||||
canon_resolved_type->id == TypeTableEntryIdNumLitFloat) &&
|
||||
} else if ((resolved_type->id == TypeTableEntryIdFloat ||
|
||||
resolved_type->id == TypeTableEntryIdNumLitFloat) &&
|
||||
(op_id == IrBinOpAdd ||
|
||||
op_id == IrBinOpSub ||
|
||||
op_id == IrBinOpMult ||
|
||||
@ -7751,7 +7729,7 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
|
||||
bin_op_instruction->base.other = &bin_op_instruction->base;
|
||||
|
||||
int err;
|
||||
if ((err = ir_eval_math_op(canon_resolved_type, op1_val, op_id, op2_val, out_val))) {
|
||||
if ((err = ir_eval_math_op(resolved_type, op1_val, op_id, op2_val, out_val))) {
|
||||
if (err == ErrorDivByZero) {
|
||||
ir_add_error_node(ira, bin_op_instruction->base.source_node,
|
||||
buf_sprintf("division by zero is undefined"));
|
||||
@ -7776,13 +7754,13 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
|
||||
|
||||
static TypeTableEntry *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *instruction) {
|
||||
IrInstruction *op1 = instruction->op1->other;
|
||||
TypeTableEntry *op1_canon_type = get_underlying_type(op1->value.type);
|
||||
if (type_is_invalid(op1_canon_type))
|
||||
TypeTableEntry *op1_type = op1->value.type;
|
||||
if (type_is_invalid(op1_type))
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
|
||||
IrInstruction *op2 = instruction->op2->other;
|
||||
TypeTableEntry *op2_canon_type = get_underlying_type(op2->value.type);
|
||||
if (type_is_invalid(op2_canon_type))
|
||||
TypeTableEntry *op2_type = op2->value.type;
|
||||
if (type_is_invalid(op2_type))
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
|
||||
ConstExprValue *op1_val = ir_resolve_const(ira, op1, UndefBad);
|
||||
@ -7797,22 +7775,22 @@ static TypeTableEntry *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *
|
||||
size_t op1_array_index;
|
||||
size_t op1_array_end;
|
||||
TypeTableEntry *child_type;
|
||||
if (op1_canon_type->id == TypeTableEntryIdArray) {
|
||||
child_type = op1_canon_type->data.array.child_type;
|
||||
if (op1_type->id == TypeTableEntryIdArray) {
|
||||
child_type = op1_type->data.array.child_type;
|
||||
op1_array_val = op1_val;
|
||||
op1_array_index = 0;
|
||||
op1_array_end = op1_canon_type->data.array.len;
|
||||
} else if (op1_canon_type->id == TypeTableEntryIdPointer &&
|
||||
op1_canon_type->data.pointer.child_type == ira->codegen->builtin_types.entry_u8 &&
|
||||
op1_array_end = op1_type->data.array.len;
|
||||
} else if (op1_type->id == TypeTableEntryIdPointer &&
|
||||
op1_type->data.pointer.child_type == ira->codegen->builtin_types.entry_u8 &&
|
||||
op1_val->data.x_ptr.special == ConstPtrSpecialBaseArray &&
|
||||
op1_val->data.x_ptr.data.base_array.is_cstr)
|
||||
{
|
||||
child_type = op1_canon_type->data.pointer.child_type;
|
||||
child_type = op1_type->data.pointer.child_type;
|
||||
op1_array_val = op1_val->data.x_ptr.data.base_array.array_val;
|
||||
op1_array_index = op1_val->data.x_ptr.data.base_array.elem_index;
|
||||
op1_array_end = op1_array_val->type->data.array.len - 1;
|
||||
} else if (is_slice(op1_canon_type)) {
|
||||
TypeTableEntry *ptr_type = op1_canon_type->data.structure.fields[slice_ptr_index].type_entry;
|
||||
} else if (is_slice(op1_type)) {
|
||||
TypeTableEntry *ptr_type = op1_type->data.structure.fields[slice_ptr_index].type_entry;
|
||||
child_type = ptr_type->data.pointer.child_type;
|
||||
ConstExprValue *ptr_val = &op1_val->data.x_struct.fields[slice_ptr_index];
|
||||
assert(ptr_val->data.x_ptr.special == ConstPtrSpecialBaseArray);
|
||||
@ -7822,15 +7800,14 @@ static TypeTableEntry *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *
|
||||
} else {
|
||||
ir_add_error(ira, op1,
|
||||
buf_sprintf("expected array or C string literal, found '%s'", buf_ptr(&op1->value.type->name)));
|
||||
// TODO if meta_type is type decl, add note pointing to type decl declaration
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
}
|
||||
|
||||
ConstExprValue *op2_array_val;
|
||||
size_t op2_array_index;
|
||||
size_t op2_array_end;
|
||||
if (op2_canon_type->id == TypeTableEntryIdArray) {
|
||||
if (op2_canon_type->data.array.child_type != child_type) {
|
||||
if (op2_type->id == TypeTableEntryIdArray) {
|
||||
if (op2_type->data.array.child_type != child_type) {
|
||||
ir_add_error(ira, op2, buf_sprintf("expected array of type '%s', found '%s'",
|
||||
buf_ptr(&child_type->name),
|
||||
buf_ptr(&op2->value.type->name)));
|
||||
@ -7839,8 +7816,8 @@ static TypeTableEntry *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *
|
||||
op2_array_val = op2_val;
|
||||
op2_array_index = 0;
|
||||
op2_array_end = op2_array_val->type->data.array.len;
|
||||
} else if (op2_canon_type->id == TypeTableEntryIdPointer &&
|
||||
op2_canon_type->data.pointer.child_type == ira->codegen->builtin_types.entry_u8 &&
|
||||
} else if (op2_type->id == TypeTableEntryIdPointer &&
|
||||
op2_type->data.pointer.child_type == ira->codegen->builtin_types.entry_u8 &&
|
||||
op2_val->data.x_ptr.special == ConstPtrSpecialBaseArray &&
|
||||
op2_val->data.x_ptr.data.base_array.is_cstr)
|
||||
{
|
||||
@ -7853,8 +7830,8 @@ static TypeTableEntry *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *
|
||||
op2_array_val = op2_val->data.x_ptr.data.base_array.array_val;
|
||||
op2_array_index = op2_val->data.x_ptr.data.base_array.elem_index;
|
||||
op2_array_end = op2_array_val->type->data.array.len - 1;
|
||||
} else if (is_slice(op2_canon_type)) {
|
||||
TypeTableEntry *ptr_type = op2_canon_type->data.structure.fields[slice_ptr_index].type_entry;
|
||||
} else if (is_slice(op2_type)) {
|
||||
TypeTableEntry *ptr_type = op2_type->data.structure.fields[slice_ptr_index].type_entry;
|
||||
if (ptr_type->data.pointer.child_type != child_type) {
|
||||
ir_add_error(ira, op2, buf_sprintf("expected array of type '%s', found '%s'",
|
||||
buf_ptr(&child_type->name),
|
||||
@ -7869,7 +7846,6 @@ static TypeTableEntry *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *
|
||||
} else {
|
||||
ir_add_error(ira, op2,
|
||||
buf_sprintf("expected array or C string literal, found '%s'", buf_ptr(&op2->value.type->name)));
|
||||
// TODO if meta_type is type decl, add note pointing to type decl declaration
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
}
|
||||
|
||||
@ -7878,7 +7854,7 @@ static TypeTableEntry *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *
|
||||
TypeTableEntry *result_type;
|
||||
ConstExprValue *out_array_val;
|
||||
size_t new_len = (op1_array_end - op1_array_index) + (op2_array_end - op2_array_index);
|
||||
if (op1_canon_type->id == TypeTableEntryIdArray || op2_canon_type->id == TypeTableEntryIdArray) {
|
||||
if (op1_type->id == TypeTableEntryIdArray || op2_type->id == TypeTableEntryIdArray) {
|
||||
result_type = get_array_type(ira->codegen, child_type, new_len);
|
||||
|
||||
out_array_val = out_val;
|
||||
@ -7931,14 +7907,13 @@ static TypeTableEntry *ir_analyze_array_mult(IrAnalyze *ira, IrInstructionBinOp
|
||||
if (!ir_resolve_usize(ira, op2, &mult_amt))
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
|
||||
TypeTableEntry *array_canon_type = get_underlying_type(op1->value.type);
|
||||
if (array_canon_type->id != TypeTableEntryIdArray) {
|
||||
TypeTableEntry *array_type = op1->value.type;
|
||||
if (array_type->id != TypeTableEntryIdArray) {
|
||||
ir_add_error(ira, op1, buf_sprintf("expected array type, found '%s'", buf_ptr(&op1->value.type->name)));
|
||||
// TODO if meta_type is type decl, add note pointing to type decl declaration
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
}
|
||||
|
||||
uint64_t old_array_len = array_canon_type->data.array.len;
|
||||
uint64_t old_array_len = array_type->data.array.len;
|
||||
|
||||
BigNum array_len;
|
||||
bignum_init_unsigned(&array_len, old_array_len);
|
||||
@ -7961,7 +7936,7 @@ static TypeTableEntry *ir_analyze_array_mult(IrAnalyze *ira, IrInstructionBinOp
|
||||
}
|
||||
assert(i == new_array_len);
|
||||
|
||||
TypeTableEntry *child_type = array_canon_type->data.array.child_type;
|
||||
TypeTableEntry *child_type = array_type->data.array.child_type;
|
||||
return get_array_type(ira->codegen, child_type, new_array_len);
|
||||
}
|
||||
|
||||
@ -8033,7 +8008,7 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc
|
||||
AstNode *source_node = decl_var_instruction->base.source_node;
|
||||
|
||||
IrInstruction *casted_init_value = ir_implicit_cast(ira, init_value, explicit_type);
|
||||
TypeTableEntry *result_type = get_underlying_type(casted_init_value->value.type);
|
||||
TypeTableEntry *result_type = casted_init_value->value.type;
|
||||
if (type_is_invalid(result_type)) {
|
||||
result_type = ira->codegen->builtin_types.entry_invalid;
|
||||
}
|
||||
@ -8041,8 +8016,6 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc
|
||||
bool is_comptime_var = ir_get_var_is_comptime(var);
|
||||
|
||||
switch (result_type->id) {
|
||||
case TypeTableEntryIdTypeDecl:
|
||||
zig_unreachable();
|
||||
case TypeTableEntryIdInvalid:
|
||||
break; // handled above
|
||||
case TypeTableEntryIdNumLitFloat:
|
||||
@ -8057,6 +8030,7 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc
|
||||
case TypeTableEntryIdVar:
|
||||
case TypeTableEntryIdBlock:
|
||||
case TypeTableEntryIdNullLit:
|
||||
case TypeTableEntryIdOpaque:
|
||||
ir_add_error_node(ira, source_node,
|
||||
buf_sprintf("variable of type '%s' not allowed", buf_ptr(&result_type->name)));
|
||||
result_type = ira->codegen->builtin_types.entry_invalid;
|
||||
@ -8670,14 +8644,11 @@ static TypeTableEntry *ir_analyze_unary_prefix_op_err(IrAnalyze *ira, IrInstruct
|
||||
IrInstruction *value = un_op_instruction->value->other;
|
||||
|
||||
TypeTableEntry *meta_type = ir_resolve_type(ira, value);
|
||||
TypeTableEntry *underlying_meta_type = get_underlying_type(meta_type);
|
||||
|
||||
if (type_is_invalid(underlying_meta_type))
|
||||
if (type_is_invalid(meta_type))
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
|
||||
|
||||
switch (underlying_meta_type->id) {
|
||||
case TypeTableEntryIdTypeDecl:
|
||||
switch (meta_type->id) {
|
||||
case TypeTableEntryIdInvalid: // handled above
|
||||
zig_unreachable();
|
||||
|
||||
@ -8712,9 +8683,9 @@ static TypeTableEntry *ir_analyze_unary_prefix_op_err(IrAnalyze *ira, IrInstruct
|
||||
case TypeTableEntryIdUnreachable:
|
||||
case TypeTableEntryIdVar:
|
||||
case TypeTableEntryIdArgTuple:
|
||||
case TypeTableEntryIdOpaque:
|
||||
ir_add_error_node(ira, un_op_instruction->base.source_node,
|
||||
buf_sprintf("unable to wrap type '%s' in error type", buf_ptr(&meta_type->name)));
|
||||
// TODO if meta_type is type decl, add note pointing to type decl declaration
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
}
|
||||
zig_unreachable();
|
||||
@ -8756,13 +8727,11 @@ static TypeTableEntry *ir_analyze_dereference(IrAnalyze *ira, IrInstructionUnOp
|
||||
static TypeTableEntry *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) {
|
||||
IrInstruction *value = un_op_instruction->value->other;
|
||||
TypeTableEntry *type_entry = ir_resolve_type(ira, value);
|
||||
TypeTableEntry *canon_type = get_underlying_type(type_entry);
|
||||
if (type_is_invalid(canon_type))
|
||||
if (type_is_invalid(type_entry))
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
switch (canon_type->id) {
|
||||
switch (type_entry->id) {
|
||||
case TypeTableEntryIdInvalid:
|
||||
case TypeTableEntryIdVar:
|
||||
case TypeTableEntryIdTypeDecl:
|
||||
zig_unreachable();
|
||||
case TypeTableEntryIdMetaType:
|
||||
case TypeTableEntryIdVoid:
|
||||
@ -8793,9 +8762,9 @@ static TypeTableEntry *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op
|
||||
return ira->codegen->builtin_types.entry_type;
|
||||
}
|
||||
case TypeTableEntryIdUnreachable:
|
||||
case TypeTableEntryIdOpaque:
|
||||
ir_add_error_node(ira, un_op_instruction->base.source_node,
|
||||
buf_sprintf("type '%s' not nullable", buf_ptr(&type_entry->name)));
|
||||
// TODO if it's a type decl, put an error note here pointing to the decl
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
}
|
||||
zig_unreachable();
|
||||
@ -9406,23 +9375,6 @@ static TypeTableEntry *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source
|
||||
return ir_analyze_const_ptr(ira, source_instruction, const_val, fn_entry->type_entry,
|
||||
ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile);
|
||||
}
|
||||
case TldIdTypeDef:
|
||||
{
|
||||
TldTypeDef *tld_typedef = (TldTypeDef *)tld;
|
||||
assert(tld_typedef->type_entry);
|
||||
|
||||
// TODO instead of allocating this every time, put it in the tld value and we can reference
|
||||
// the same one every time
|
||||
ConstExprValue *const_val = allocate<ConstExprValue>(1);
|
||||
const_val->special = ConstValSpecialStatic;
|
||||
const_val->type = ira->codegen->builtin_types.entry_type;
|
||||
const_val->data.x_type = tld_typedef->type_entry;
|
||||
|
||||
bool ptr_is_const = true;
|
||||
bool ptr_is_volatile = false;
|
||||
return ir_analyze_const_ptr(ira, source_instruction, const_val, ira->codegen->builtin_types.entry_type,
|
||||
ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile);
|
||||
}
|
||||
}
|
||||
zig_unreachable();
|
||||
}
|
||||
@ -9726,9 +9678,9 @@ static TypeTableEntry *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructi
|
||||
case TypeTableEntryIdEnum:
|
||||
case TypeTableEntryIdUnion:
|
||||
case TypeTableEntryIdFn:
|
||||
case TypeTableEntryIdTypeDecl:
|
||||
case TypeTableEntryIdEnumTag:
|
||||
case TypeTableEntryIdArgTuple:
|
||||
case TypeTableEntryIdOpaque:
|
||||
{
|
||||
ConstExprValue *out_val = ir_build_const_from(ira, &typeof_instruction->base);
|
||||
out_val->data.x_type = type_entry;
|
||||
@ -9990,12 +9942,10 @@ static TypeTableEntry *ir_analyze_instruction_slice_type(IrAnalyze *ira,
|
||||
bool is_const = slice_type_instruction->is_const;
|
||||
|
||||
TypeTableEntry *resolved_child_type = ir_resolve_type(ira, child_type);
|
||||
TypeTableEntry *canon_child_type = get_underlying_type(resolved_child_type);
|
||||
if (type_is_invalid(canon_child_type))
|
||||
if (type_is_invalid(resolved_child_type))
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
|
||||
switch (canon_child_type->id) {
|
||||
case TypeTableEntryIdTypeDecl:
|
||||
switch (resolved_child_type->id) {
|
||||
case TypeTableEntryIdInvalid: // handled above
|
||||
zig_unreachable();
|
||||
case TypeTableEntryIdVar:
|
||||
@ -10004,9 +9954,9 @@ static TypeTableEntry *ir_analyze_instruction_slice_type(IrAnalyze *ira,
|
||||
case TypeTableEntryIdNullLit:
|
||||
case TypeTableEntryIdBlock:
|
||||
case TypeTableEntryIdArgTuple:
|
||||
case TypeTableEntryIdOpaque:
|
||||
ir_add_error_node(ira, slice_type_instruction->base.source_node,
|
||||
buf_sprintf("slice of type '%s' not allowed", buf_ptr(&resolved_child_type->name)));
|
||||
// TODO if this is a typedecl, add error note showing the declaration of the type decl
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
case TypeTableEntryIdMetaType:
|
||||
case TypeTableEntryIdVoid:
|
||||
@ -10100,11 +10050,9 @@ static TypeTableEntry *ir_analyze_instruction_array_type(IrAnalyze *ira,
|
||||
|
||||
IrInstruction *child_type_value = array_type_instruction->child_type->other;
|
||||
TypeTableEntry *child_type = ir_resolve_type(ira, child_type_value);
|
||||
TypeTableEntry *canon_child_type = get_underlying_type(child_type);
|
||||
if (type_is_invalid(canon_child_type))
|
||||
if (type_is_invalid(child_type))
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
switch (canon_child_type->id) {
|
||||
case TypeTableEntryIdTypeDecl:
|
||||
switch (child_type->id) {
|
||||
case TypeTableEntryIdInvalid: // handled above
|
||||
zig_unreachable();
|
||||
case TypeTableEntryIdVar:
|
||||
@ -10113,9 +10061,9 @@ static TypeTableEntry *ir_analyze_instruction_array_type(IrAnalyze *ira,
|
||||
case TypeTableEntryIdNullLit:
|
||||
case TypeTableEntryIdBlock:
|
||||
case TypeTableEntryIdArgTuple:
|
||||
case TypeTableEntryIdOpaque:
|
||||
ir_add_error_node(ira, array_type_instruction->base.source_node,
|
||||
buf_sprintf("array of type '%s' not allowed", buf_ptr(&child_type->name)));
|
||||
// TODO if this is a typedecl, add error note showing the declaration of the type decl
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
case TypeTableEntryIdMetaType:
|
||||
case TypeTableEntryIdVoid:
|
||||
@ -10172,15 +10120,13 @@ static TypeTableEntry *ir_analyze_instruction_size_of(IrAnalyze *ira,
|
||||
{
|
||||
IrInstruction *type_value = size_of_instruction->type_value->other;
|
||||
TypeTableEntry *type_entry = ir_resolve_type(ira, type_value);
|
||||
TypeTableEntry *canon_type_entry = get_underlying_type(type_entry);
|
||||
|
||||
ensure_complete_type(ira->codegen, type_entry);
|
||||
if (type_is_invalid(canon_type_entry))
|
||||
if (type_is_invalid(type_entry))
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
|
||||
switch (canon_type_entry->id) {
|
||||
switch (type_entry->id) {
|
||||
case TypeTableEntryIdInvalid: // handled above
|
||||
case TypeTableEntryIdTypeDecl:
|
||||
zig_unreachable();
|
||||
case TypeTableEntryIdVar:
|
||||
case TypeTableEntryIdUnreachable:
|
||||
@ -10193,9 +10139,9 @@ static TypeTableEntry *ir_analyze_instruction_size_of(IrAnalyze *ira,
|
||||
case TypeTableEntryIdMetaType:
|
||||
case TypeTableEntryIdNamespace:
|
||||
case TypeTableEntryIdArgTuple:
|
||||
case TypeTableEntryIdOpaque:
|
||||
ir_add_error_node(ira, size_of_instruction->base.source_node,
|
||||
buf_sprintf("no size available for type '%s'", buf_ptr(&type_entry->name)));
|
||||
// TODO if this is a typedecl, add error note showing the declaration of the type decl
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
case TypeTableEntryIdVoid:
|
||||
case TypeTableEntryIdBool:
|
||||
@ -10516,15 +10462,13 @@ static TypeTableEntry *ir_analyze_instruction_switch_target(IrAnalyze *ira,
|
||||
if (pointee_val->special == ConstValSpecialRuntime)
|
||||
pointee_val = nullptr;
|
||||
}
|
||||
TypeTableEntry *canon_target_type = get_underlying_type(target_type);
|
||||
ensure_complete_type(ira->codegen, target_type);
|
||||
if (type_is_invalid(canon_target_type))
|
||||
if (type_is_invalid(target_type))
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
|
||||
switch (canon_target_type->id) {
|
||||
switch (target_type->id) {
|
||||
case TypeTableEntryIdInvalid:
|
||||
case TypeTableEntryIdVar:
|
||||
case TypeTableEntryIdTypeDecl:
|
||||
zig_unreachable();
|
||||
case TypeTableEntryIdMetaType:
|
||||
case TypeTableEntryIdVoid:
|
||||
@ -10576,9 +10520,9 @@ static TypeTableEntry *ir_analyze_instruction_switch_target(IrAnalyze *ira,
|
||||
case TypeTableEntryIdBlock:
|
||||
case TypeTableEntryIdBoundFn:
|
||||
case TypeTableEntryIdArgTuple:
|
||||
case TypeTableEntryIdOpaque:
|
||||
ir_add_error(ira, &switch_target_instruction->base,
|
||||
buf_sprintf("invalid switch target type '%s'", buf_ptr(&target_type->name)));
|
||||
// TODO if this is a typedecl, add error note showing the declaration of the type decl
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
}
|
||||
zig_unreachable();
|
||||
@ -10630,9 +10574,8 @@ static TypeTableEntry *ir_analyze_instruction_switch_var(IrAnalyze *ira, IrInstr
|
||||
return get_pointer_to_type(ira->codegen, field->type_entry,
|
||||
target_value_ptr->value.type->data.pointer.is_const);
|
||||
} else {
|
||||
ErrorMsg *msg = ir_add_error(ira, &instruction->base,
|
||||
ir_add_error(ira, &instruction->base,
|
||||
buf_sprintf("switch on type '%s' provides no expression parameter", buf_ptr(&target_type->name)));
|
||||
ir_add_typedef_err_note(ira, msg, target_type);
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
}
|
||||
}
|
||||
@ -10743,13 +10686,13 @@ static TypeTableEntry *ir_analyze_instruction_array_len(IrAnalyze *ira,
|
||||
IrInstructionArrayLen *array_len_instruction)
|
||||
{
|
||||
IrInstruction *array_value = array_len_instruction->array_value->other;
|
||||
TypeTableEntry *canon_type = get_underlying_type(array_value->value.type);
|
||||
if (type_is_invalid(canon_type)) {
|
||||
TypeTableEntry *type_entry = array_value->value.type;
|
||||
if (type_is_invalid(type_entry)) {
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
} else if (canon_type->id == TypeTableEntryIdArray) {
|
||||
} else if (type_entry->id == TypeTableEntryIdArray) {
|
||||
return ir_analyze_const_usize(ira, &array_len_instruction->base,
|
||||
canon_type->data.array.len);
|
||||
} else if (is_slice(canon_type)) {
|
||||
type_entry->data.array.len);
|
||||
} else if (is_slice(type_entry)) {
|
||||
if (array_value->value.special != ConstValSpecialRuntime) {
|
||||
ConstExprValue *len_val = &array_value->value.data.x_struct.fields[slice_len_index];
|
||||
if (len_val->special != ConstValSpecialRuntime) {
|
||||
@ -10757,7 +10700,7 @@ static TypeTableEntry *ir_analyze_instruction_array_len(IrAnalyze *ira,
|
||||
len_val->data.x_bignum.data.x_uint);
|
||||
}
|
||||
}
|
||||
TypeStructField *field = &canon_type->data.structure.fields[slice_len_index];
|
||||
TypeStructField *field = &type_entry->data.structure.fields[slice_len_index];
|
||||
IrInstruction *len_ptr = ir_build_struct_field_ptr(&ira->new_irb, array_len_instruction->base.scope,
|
||||
array_len_instruction->base.source_node, array_value, field);
|
||||
len_ptr->value.type = get_pointer_to_type(ira->codegen, ira->codegen->builtin_types.entry_usize, true);
|
||||
@ -10766,7 +10709,6 @@ static TypeTableEntry *ir_analyze_instruction_array_len(IrAnalyze *ira,
|
||||
} else {
|
||||
ir_add_error_node(ira, array_len_instruction->base.source_node,
|
||||
buf_sprintf("type '%s' has no field 'len'", buf_ptr(&array_value->value.type->name)));
|
||||
// TODO if this is a typedecl, add error note showing the declaration of the type decl
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
}
|
||||
}
|
||||
@ -11049,29 +10991,28 @@ static TypeTableEntry *ir_analyze_min_max(IrAnalyze *ira, IrInstruction *source_
|
||||
IrInstruction *target_type_value, bool is_max)
|
||||
{
|
||||
TypeTableEntry *target_type = ir_resolve_type(ira, target_type_value);
|
||||
TypeTableEntry *canon_type = get_underlying_type(target_type);
|
||||
if (type_is_invalid(canon_type))
|
||||
if (type_is_invalid(target_type))
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
switch (canon_type->id) {
|
||||
switch (target_type->id) {
|
||||
case TypeTableEntryIdInvalid:
|
||||
zig_unreachable();
|
||||
case TypeTableEntryIdInt:
|
||||
{
|
||||
ConstExprValue *out_val = ir_build_const_from(ira, source_instruction);
|
||||
eval_min_max_value(ira->codegen, canon_type, out_val, is_max);
|
||||
eval_min_max_value(ira->codegen, target_type, out_val, is_max);
|
||||
return ira->codegen->builtin_types.entry_num_lit_int;
|
||||
}
|
||||
case TypeTableEntryIdFloat:
|
||||
{
|
||||
ConstExprValue *out_val = ir_build_const_from(ira, source_instruction);
|
||||
eval_min_max_value(ira->codegen, canon_type, out_val, is_max);
|
||||
eval_min_max_value(ira->codegen, target_type, out_val, is_max);
|
||||
return ira->codegen->builtin_types.entry_num_lit_float;
|
||||
}
|
||||
case TypeTableEntryIdBool:
|
||||
case TypeTableEntryIdVoid:
|
||||
{
|
||||
ConstExprValue *out_val = ir_build_const_from(ira, source_instruction);
|
||||
eval_min_max_value(ira->codegen, canon_type, out_val, is_max);
|
||||
eval_min_max_value(ira->codegen, target_type, out_val, is_max);
|
||||
return target_type;
|
||||
}
|
||||
case TypeTableEntryIdEnumTag:
|
||||
@ -11092,18 +11033,17 @@ static TypeTableEntry *ir_analyze_min_max(IrAnalyze *ira, IrInstruction *source_
|
||||
case TypeTableEntryIdEnum:
|
||||
case TypeTableEntryIdUnion:
|
||||
case TypeTableEntryIdFn:
|
||||
case TypeTableEntryIdTypeDecl:
|
||||
case TypeTableEntryIdNamespace:
|
||||
case TypeTableEntryIdBlock:
|
||||
case TypeTableEntryIdBoundFn:
|
||||
case TypeTableEntryIdArgTuple:
|
||||
case TypeTableEntryIdOpaque:
|
||||
{
|
||||
const char *err_format = is_max ?
|
||||
"no max value available for type '%s'" :
|
||||
"no min value available for type '%s'";
|
||||
ir_add_error(ira, source_instruction,
|
||||
buf_sprintf(err_format, buf_ptr(&target_type->name)));
|
||||
// TODO if this is a typedecl, add error note showing the declaration of the type decl
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
}
|
||||
}
|
||||
@ -11508,14 +11448,11 @@ static TypeTableEntry *ir_analyze_instruction_div_exact(IrAnalyze *ira, IrInstru
|
||||
if (type_is_invalid(result_type))
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
|
||||
TypeTableEntry *canon_type = get_underlying_type(result_type);
|
||||
|
||||
if (canon_type->id != TypeTableEntryIdInt &&
|
||||
canon_type->id != TypeTableEntryIdNumLitInt)
|
||||
if (result_type->id != TypeTableEntryIdInt &&
|
||||
result_type->id != TypeTableEntryIdNumLitInt)
|
||||
{
|
||||
ir_add_error(ira, &instruction->base,
|
||||
buf_sprintf("expected integer type, found '%s'", buf_ptr(&result_type->name)));
|
||||
// TODO if meta_type is type decl, add note pointing to type decl declaration
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
}
|
||||
|
||||
@ -11563,49 +11500,42 @@ static TypeTableEntry *ir_analyze_instruction_div_exact(IrAnalyze *ira, IrInstru
|
||||
static TypeTableEntry *ir_analyze_instruction_truncate(IrAnalyze *ira, IrInstructionTruncate *instruction) {
|
||||
IrInstruction *dest_type_value = instruction->dest_type->other;
|
||||
TypeTableEntry *dest_type = ir_resolve_type(ira, dest_type_value);
|
||||
TypeTableEntry *canon_dest_type = get_underlying_type(dest_type);
|
||||
|
||||
if (type_is_invalid(canon_dest_type))
|
||||
if (type_is_invalid(dest_type))
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
|
||||
if (canon_dest_type->id != TypeTableEntryIdInt &&
|
||||
canon_dest_type->id != TypeTableEntryIdNumLitInt)
|
||||
if (dest_type->id != TypeTableEntryIdInt &&
|
||||
dest_type->id != TypeTableEntryIdNumLitInt)
|
||||
{
|
||||
ir_add_error(ira, dest_type_value, buf_sprintf("expected integer type, found '%s'", buf_ptr(&dest_type->name)));
|
||||
// TODO if meta_type is type decl, add note pointing to type decl declaration
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
}
|
||||
|
||||
IrInstruction *target = instruction->target->other;
|
||||
TypeTableEntry *src_type = target->value.type;
|
||||
TypeTableEntry *canon_src_type = get_underlying_type(src_type);
|
||||
if (type_is_invalid(canon_src_type))
|
||||
if (type_is_invalid(src_type))
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
|
||||
if (canon_src_type->id != TypeTableEntryIdInt &&
|
||||
canon_src_type->id != TypeTableEntryIdNumLitInt)
|
||||
if (src_type->id != TypeTableEntryIdInt &&
|
||||
src_type->id != TypeTableEntryIdNumLitInt)
|
||||
{
|
||||
ir_add_error(ira, target, buf_sprintf("expected integer type, found '%s'", buf_ptr(&src_type->name)));
|
||||
// TODO if meta_type is type decl, add note pointing to type decl declaration
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
}
|
||||
|
||||
if (canon_src_type->data.integral.is_signed != canon_dest_type->data.integral.is_signed) {
|
||||
const char *sign_str = canon_dest_type->data.integral.is_signed ? "signed" : "unsigned";
|
||||
if (src_type->data.integral.is_signed != dest_type->data.integral.is_signed) {
|
||||
const char *sign_str = dest_type->data.integral.is_signed ? "signed" : "unsigned";
|
||||
ir_add_error(ira, target, buf_sprintf("expected %s integer type, found '%s'", sign_str, buf_ptr(&src_type->name)));
|
||||
// TODO if meta_type is type decl, add note pointing to type decl declaration
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
} else if (canon_src_type->data.integral.bit_count < canon_dest_type->data.integral.bit_count) {
|
||||
} else if (src_type->data.integral.bit_count < dest_type->data.integral.bit_count) {
|
||||
ir_add_error(ira, target, buf_sprintf("type '%s' has fewer bits than destination type '%s'",
|
||||
buf_ptr(&src_type->name), buf_ptr(&dest_type->name)));
|
||||
// TODO if meta_type is type decl, add note pointing to type decl declaration
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
}
|
||||
|
||||
if (target->value.special == ConstValSpecialStatic) {
|
||||
ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
|
||||
bignum_init_bignum(&out_val->data.x_bignum, &target->value.data.x_bignum);
|
||||
bignum_truncate(&out_val->data.x_bignum, canon_dest_type->data.integral.bit_count);
|
||||
bignum_truncate(&out_val->data.x_bignum, dest_type->data.integral.bit_count);
|
||||
return dest_type;
|
||||
}
|
||||
|
||||
@ -11663,7 +11593,7 @@ static TypeTableEntry *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructi
|
||||
if (type_is_invalid(count_value->value.type))
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
|
||||
TypeTableEntry *dest_uncasted_type = get_underlying_type(dest_ptr->value.type);
|
||||
TypeTableEntry *dest_uncasted_type = dest_ptr->value.type;
|
||||
bool dest_is_volatile = (dest_uncasted_type->id == TypeTableEntryIdPointer) &&
|
||||
dest_uncasted_type->data.pointer.is_volatile;
|
||||
|
||||
@ -11749,8 +11679,8 @@ static TypeTableEntry *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructi
|
||||
if (type_is_invalid(count_value->value.type))
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
|
||||
TypeTableEntry *dest_uncasted_type = get_underlying_type(dest_ptr->value.type);
|
||||
TypeTableEntry *src_uncasted_type = get_underlying_type(src_ptr->value.type);
|
||||
TypeTableEntry *dest_uncasted_type = dest_ptr->value.type;
|
||||
TypeTableEntry *src_uncasted_type = src_ptr->value.type;
|
||||
bool dest_is_volatile = (dest_uncasted_type->id == TypeTableEntryIdPointer) &&
|
||||
dest_uncasted_type->data.pointer.is_volatile;
|
||||
bool src_is_volatile = (src_uncasted_type->id == TypeTableEntryIdPointer) &&
|
||||
@ -11866,8 +11796,7 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio
|
||||
|
||||
TypeTableEntry *ptr_type = ptr_ptr->value.type;
|
||||
assert(ptr_type->id == TypeTableEntryIdPointer);
|
||||
TypeTableEntry *non_canon_array_type = ptr_type->data.pointer.child_type;
|
||||
TypeTableEntry *canon_array_type = get_underlying_type(non_canon_array_type);
|
||||
TypeTableEntry *array_type = ptr_type->data.pointer.child_type;
|
||||
|
||||
IrInstruction *start = instruction->start->other;
|
||||
if (type_is_invalid(start->value.type))
|
||||
@ -11892,22 +11821,21 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio
|
||||
|
||||
TypeTableEntry *return_type;
|
||||
|
||||
if (canon_array_type->id == TypeTableEntryIdArray) {
|
||||
return_type = get_slice_type(ira->codegen, canon_array_type->data.array.child_type, instruction->is_const);
|
||||
} else if (canon_array_type->id == TypeTableEntryIdPointer) {
|
||||
return_type = get_slice_type(ira->codegen, canon_array_type->data.pointer.child_type, instruction->is_const);
|
||||
if (array_type->id == TypeTableEntryIdArray) {
|
||||
return_type = get_slice_type(ira->codegen, array_type->data.array.child_type, instruction->is_const);
|
||||
} else if (array_type->id == TypeTableEntryIdPointer) {
|
||||
return_type = get_slice_type(ira->codegen, array_type->data.pointer.child_type, instruction->is_const);
|
||||
if (!end) {
|
||||
ir_add_error(ira, &instruction->base, buf_sprintf("slice of pointer must include end value"));
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
}
|
||||
} else if (is_slice(canon_array_type)) {
|
||||
} else if (is_slice(array_type)) {
|
||||
return_type = get_slice_type(ira->codegen,
|
||||
canon_array_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.child_type,
|
||||
array_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.child_type,
|
||||
instruction->is_const);
|
||||
} else {
|
||||
ir_add_error(ira, &instruction->base,
|
||||
buf_sprintf("slice of non-array type '%s'", buf_ptr(&non_canon_array_type->name)));
|
||||
// TODO if this is a typedecl, add error note showing the declaration of the type decl
|
||||
buf_sprintf("slice of non-array type '%s'", buf_ptr(&array_type->name)));
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
}
|
||||
|
||||
@ -11919,12 +11847,12 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio
|
||||
ConstExprValue *parent_ptr;
|
||||
size_t abs_offset;
|
||||
size_t rel_end;
|
||||
if (canon_array_type->id == TypeTableEntryIdArray) {
|
||||
if (array_type->id == TypeTableEntryIdArray) {
|
||||
array_val = const_ptr_pointee(&ptr_ptr->value);
|
||||
abs_offset = 0;
|
||||
rel_end = canon_array_type->data.array.len;
|
||||
rel_end = array_type->data.array.len;
|
||||
parent_ptr = nullptr;
|
||||
} else if (canon_array_type->id == TypeTableEntryIdPointer) {
|
||||
} else if (array_type->id == TypeTableEntryIdPointer) {
|
||||
parent_ptr = const_ptr_pointee(&ptr_ptr->value);
|
||||
switch (parent_ptr->data.x_ptr.special) {
|
||||
case ConstPtrSpecialInvalid:
|
||||
@ -11946,7 +11874,7 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio
|
||||
array_val = nullptr;
|
||||
break;
|
||||
}
|
||||
} else if (is_slice(canon_array_type)) {
|
||||
} else if (is_slice(array_type)) {
|
||||
ConstExprValue *slice_ptr = const_ptr_pointee(&ptr_ptr->value);
|
||||
parent_ptr = &slice_ptr->data.x_struct.fields[slice_ptr_index];
|
||||
ConstExprValue *len_val = &slice_ptr->data.x_struct.fields[slice_len_index];
|
||||
@ -12005,7 +11933,7 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio
|
||||
if (array_val) {
|
||||
size_t index = abs_offset + start_scalar;
|
||||
init_const_ptr_array(ira->codegen, ptr_val, array_val, index, instruction->is_const);
|
||||
if (canon_array_type->id == TypeTableEntryIdArray) {
|
||||
if (array_type->id == TypeTableEntryIdArray) {
|
||||
ptr_val->data.x_ptr.mut = ptr_ptr->value.data.x_ptr.mut;
|
||||
}
|
||||
} else {
|
||||
@ -12045,17 +11973,16 @@ static TypeTableEntry *ir_analyze_instruction_member_count(IrAnalyze *ira, IrIns
|
||||
if (type_is_invalid(container->value.type))
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
TypeTableEntry *container_type = ir_resolve_type(ira, container);
|
||||
TypeTableEntry *canon_type = get_underlying_type(container_type);
|
||||
|
||||
uint64_t result;
|
||||
if (type_is_invalid(canon_type)) {
|
||||
if (type_is_invalid(container_type)) {
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
} else if (canon_type->id == TypeTableEntryIdEnum) {
|
||||
result = canon_type->data.enumeration.src_field_count;
|
||||
} else if (canon_type->id == TypeTableEntryIdStruct) {
|
||||
result = canon_type->data.structure.src_field_count;
|
||||
} else if (canon_type->id == TypeTableEntryIdUnion) {
|
||||
result = canon_type->data.unionation.src_field_count;
|
||||
} else if (container_type->id == TypeTableEntryIdEnum) {
|
||||
result = container_type->data.enumeration.src_field_count;
|
||||
} else if (container_type->id == TypeTableEntryIdStruct) {
|
||||
result = container_type->data.structure.src_field_count;
|
||||
} else if (container_type->id == TypeTableEntryIdUnion) {
|
||||
result = container_type->data.unionation.src_field_count;
|
||||
} else {
|
||||
ir_add_error(ira, &instruction->base, buf_sprintf("no value count available for type '%s'", buf_ptr(&container_type->name)));
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
@ -12112,14 +12039,12 @@ static TypeTableEntry *ir_analyze_instruction_overflow_op(IrAnalyze *ira, IrInst
|
||||
if (type_is_invalid(type_value->value.type))
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
TypeTableEntry *dest_type = ir_resolve_type(ira, type_value);
|
||||
TypeTableEntry *canon_type = get_underlying_type(dest_type);
|
||||
if (type_is_invalid(canon_type))
|
||||
if (type_is_invalid(dest_type))
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
|
||||
if (canon_type->id != TypeTableEntryIdInt) {
|
||||
if (dest_type->id != TypeTableEntryIdInt) {
|
||||
ir_add_error(ira, type_value,
|
||||
buf_sprintf("expected integer type, found '%s'", buf_ptr(&dest_type->name)));
|
||||
// TODO if this is a typedecl, add error note showing the declaration of the type decl
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
}
|
||||
|
||||
@ -12171,11 +12096,11 @@ static TypeTableEntry *ir_analyze_instruction_overflow_op(IrAnalyze *ira, IrInst
|
||||
out_val->data.x_bool = bignum_shl(dest_bignum, op1_bignum, op2_bignum);
|
||||
break;
|
||||
}
|
||||
if (!bignum_fits_in_bits(dest_bignum, canon_type->data.integral.bit_count,
|
||||
canon_type->data.integral.is_signed))
|
||||
if (!bignum_fits_in_bits(dest_bignum, dest_type->data.integral.bit_count,
|
||||
dest_type->data.integral.is_signed))
|
||||
{
|
||||
out_val->data.x_bool = true;
|
||||
bignum_truncate(dest_bignum, canon_type->data.integral.bit_count);
|
||||
bignum_truncate(dest_bignum, dest_type->data.integral.bit_count);
|
||||
}
|
||||
pointee_val->special = ConstValSpecialStatic;
|
||||
return ira->codegen->builtin_types.entry_bool;
|
||||
@ -12191,12 +12116,10 @@ static TypeTableEntry *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstruc
|
||||
if (type_is_invalid(value->value.type))
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
|
||||
TypeTableEntry *non_canon_type = value->value.type;
|
||||
|
||||
TypeTableEntry *canon_type = get_underlying_type(non_canon_type);
|
||||
if (type_is_invalid(canon_type)) {
|
||||
TypeTableEntry *type_entry = value->value.type;
|
||||
if (type_is_invalid(type_entry)) {
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
} else if (canon_type->id == TypeTableEntryIdErrorUnion) {
|
||||
} else if (type_entry->id == TypeTableEntryIdErrorUnion) {
|
||||
if (instr_is_comptime(value)) {
|
||||
ConstExprValue *err_union_val = ir_resolve_const(ira, value, UndefBad);
|
||||
if (!err_union_val)
|
||||
@ -12211,7 +12134,7 @@ static TypeTableEntry *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstruc
|
||||
|
||||
ir_build_test_err_from(&ira->new_irb, &instruction->base, value);
|
||||
return ira->codegen->builtin_types.entry_bool;
|
||||
} else if (canon_type->id == TypeTableEntryIdPureError) {
|
||||
} else if (type_entry->id == TypeTableEntryIdPureError) {
|
||||
ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
|
||||
out_val->data.x_bool = true;
|
||||
return ira->codegen->builtin_types.entry_bool;
|
||||
@ -12233,11 +12156,10 @@ static TypeTableEntry *ir_analyze_instruction_unwrap_err_code(IrAnalyze *ira,
|
||||
// This will be a pointer type because unwrap err payload IR instruction operates on a pointer to a thing.
|
||||
assert(ptr_type->id == TypeTableEntryIdPointer);
|
||||
|
||||
TypeTableEntry *non_canon_type = ptr_type->data.pointer.child_type;
|
||||
TypeTableEntry *canon_type = get_underlying_type(non_canon_type);
|
||||
if (type_is_invalid(canon_type)) {
|
||||
TypeTableEntry *type_entry = ptr_type->data.pointer.child_type;
|
||||
if (type_is_invalid(type_entry)) {
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
} else if (canon_type->id == TypeTableEntryIdErrorUnion) {
|
||||
} else if (type_entry->id == TypeTableEntryIdErrorUnion) {
|
||||
if (instr_is_comptime(value)) {
|
||||
ConstExprValue *ptr_val = ir_resolve_const(ira, value, UndefBad);
|
||||
if (!ptr_val)
|
||||
@ -12257,8 +12179,7 @@ static TypeTableEntry *ir_analyze_instruction_unwrap_err_code(IrAnalyze *ira,
|
||||
return ira->codegen->builtin_types.entry_pure_error;
|
||||
} else {
|
||||
ir_add_error(ira, value,
|
||||
buf_sprintf("expected error union type, found '%s'", buf_ptr(&non_canon_type->name)));
|
||||
// TODO if this is a typedecl, add error note showing the declaration of the type decl
|
||||
buf_sprintf("expected error union type, found '%s'", buf_ptr(&type_entry->name)));
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
}
|
||||
}
|
||||
@ -12275,12 +12196,11 @@ static TypeTableEntry *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira,
|
||||
// This will be a pointer type because unwrap err payload IR instruction operates on a pointer to a thing.
|
||||
assert(ptr_type->id == TypeTableEntryIdPointer);
|
||||
|
||||
TypeTableEntry *non_canon_type = ptr_type->data.pointer.child_type;
|
||||
TypeTableEntry *canon_type = get_underlying_type(non_canon_type);
|
||||
if (type_is_invalid(canon_type)) {
|
||||
TypeTableEntry *type_entry = ptr_type->data.pointer.child_type;
|
||||
if (type_is_invalid(type_entry)) {
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
} else if (canon_type->id == TypeTableEntryIdErrorUnion) {
|
||||
TypeTableEntry *child_type = canon_type->data.error.child_type;
|
||||
} else if (type_entry->id == TypeTableEntryIdErrorUnion) {
|
||||
TypeTableEntry *child_type = type_entry->data.error.child_type;
|
||||
TypeTableEntry *result_type = get_pointer_to_type_extra(ira->codegen, child_type,
|
||||
ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, 0, 0);
|
||||
if (instr_is_comptime(value)) {
|
||||
@ -12307,8 +12227,7 @@ static TypeTableEntry *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira,
|
||||
return result_type;
|
||||
} else {
|
||||
ir_add_error(ira, value,
|
||||
buf_sprintf("expected error union type, found '%s'", buf_ptr(&non_canon_type->name)));
|
||||
// TODO if this is a typedecl, add error note showing the declaration of the type decl
|
||||
buf_sprintf("expected error union type, found '%s'", buf_ptr(&type_entry->name)));
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
}
|
||||
|
||||
@ -12594,22 +12513,6 @@ static TypeTableEntry *ir_analyze_instruction_decl_ref(IrAnalyze *ira,
|
||||
return ref_instruction->value.type;
|
||||
}
|
||||
}
|
||||
case TldIdTypeDef:
|
||||
{
|
||||
TldTypeDef *tld_typedef = (TldTypeDef *)tld;
|
||||
TypeTableEntry *typedef_type = tld_typedef->type_entry;
|
||||
|
||||
IrInstruction *ref_instruction = ir_create_const_type(&ira->new_irb, instruction->base.scope,
|
||||
instruction->base.source_node, typedef_type);
|
||||
if (lval.is_ptr) {
|
||||
IrInstruction *ptr_inst = ir_get_ref(ira, &instruction->base, ref_instruction, true, false);
|
||||
ir_link_new_instruction(ptr_inst, &instruction->base);
|
||||
return ptr_inst->value.type;
|
||||
} else {
|
||||
ir_link_new_instruction(ref_instruction, &instruction->base);
|
||||
return ref_instruction->value.type;
|
||||
}
|
||||
}
|
||||
}
|
||||
zig_unreachable();
|
||||
}
|
||||
|
@ -219,28 +219,8 @@ static Tld *add_container_tld(Context *c, TypeTableEntry *type_entry) {
|
||||
return add_const_type(c, &type_entry->name, type_entry);
|
||||
}
|
||||
|
||||
static Tld *add_typedef_tld(Context *c, TypeTableEntry *type_decl) {
|
||||
assert(type_decl);
|
||||
assert(type_decl->id == TypeTableEntryIdTypeDecl);
|
||||
|
||||
TldTypeDef *tld_typedef = allocate<TldTypeDef>(1);
|
||||
parseh_init_tld(c, &tld_typedef->base, TldIdTypeDef, &type_decl->name);
|
||||
tld_typedef->type_entry = type_decl;
|
||||
|
||||
add_global(c, &tld_typedef->base);
|
||||
c->global_type_table.put(&type_decl->name, type_decl);
|
||||
|
||||
return &tld_typedef->base;
|
||||
}
|
||||
|
||||
static bool is_c_void_type(Context *c, TypeTableEntry *type_entry) {
|
||||
while (type_entry->id == TypeTableEntryIdTypeDecl) {
|
||||
if (type_entry == c->codegen->builtin_types.entry_c_void) {
|
||||
return true;
|
||||
}
|
||||
type_entry = type_entry->data.type_decl.child_type;
|
||||
}
|
||||
return false;
|
||||
return (type_entry == c->codegen->builtin_types.entry_c_void);
|
||||
}
|
||||
|
||||
static bool qual_type_child_is_fn_proto(const QualType &qt) {
|
||||
@ -369,7 +349,7 @@ static TypeTableEntry *resolve_type_with_table(Context *c, const Type *ty, const
|
||||
const PointerType *pointer_ty = static_cast<const PointerType*>(ty);
|
||||
QualType child_qt = pointer_ty->getPointeeType();
|
||||
TypeTableEntry *child_type = resolve_qual_type(c, child_qt, decl);
|
||||
if (get_underlying_type(child_type)->id == TypeTableEntryIdInvalid) {
|
||||
if (type_is_invalid(child_type)) {
|
||||
emit_warning(c, decl, "pointer to unresolved type");
|
||||
return c->codegen->builtin_types.entry_invalid;
|
||||
}
|
||||
@ -410,7 +390,7 @@ static TypeTableEntry *resolve_type_with_table(Context *c, const Type *ty, const
|
||||
} else {
|
||||
auto entry = type_table->maybe_get(type_name);
|
||||
if (entry) {
|
||||
if (get_underlying_type(entry->value)->id == TypeTableEntryIdInvalid) {
|
||||
if (type_is_invalid(entry->value)) {
|
||||
return c->codegen->builtin_types.entry_invalid;
|
||||
} else {
|
||||
return entry->value;
|
||||
@ -507,7 +487,7 @@ static TypeTableEntry *resolve_type_with_table(Context *c, const Type *ty, const
|
||||
fn_type_id.return_type = c->codegen->builtin_types.entry_unreachable;
|
||||
} else {
|
||||
fn_type_id.return_type = resolve_qual_type(c, fn_proto_ty->getReturnType(), decl);
|
||||
if (get_underlying_type(fn_type_id.return_type)->id == TypeTableEntryIdInvalid) {
|
||||
if (type_is_invalid(fn_type_id.return_type)) {
|
||||
emit_warning(c, decl, "unresolved function proto return type");
|
||||
return c->codegen->builtin_types.entry_invalid;
|
||||
}
|
||||
@ -522,7 +502,7 @@ static TypeTableEntry *resolve_type_with_table(Context *c, const Type *ty, const
|
||||
QualType qt = fn_proto_ty->getParamType(i);
|
||||
TypeTableEntry *param_type = resolve_qual_type(c, qt, decl);
|
||||
|
||||
if (get_underlying_type(param_type)->id == TypeTableEntryIdInvalid) {
|
||||
if (type_is_invalid(param_type)) {
|
||||
emit_warning(c, decl, "unresolved function proto parameter type");
|
||||
return c->codegen->builtin_types.entry_invalid;
|
||||
}
|
||||
@ -702,6 +682,7 @@ static void replace_with_fwd_decl(Context *c, TypeTableEntry *struct_type, Buf *
|
||||
|
||||
ZigLLVMReplaceTemporary(c->codegen->dbuilder, struct_type->di_type, replacement_di_type);
|
||||
struct_type->di_type = replacement_di_type;
|
||||
struct_type->id = TypeTableEntryIdOpaque;
|
||||
}
|
||||
|
||||
static TypeTableEntry *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) {
|
||||
@ -809,7 +790,9 @@ static TypeTableEntry *resolve_enum_decl(Context *c, const EnumDecl *enum_decl)
|
||||
|
||||
return enum_type;
|
||||
} else {
|
||||
TypeTableEntry *enum_type = get_typedecl_type(c->codegen, buf_ptr(full_type_name), tag_type_entry);
|
||||
// TODO after issue #305 is solved, make this be an enum with tag_type_entry
|
||||
// as the integer type and set the custom enum values
|
||||
TypeTableEntry *enum_type = tag_type_entry;
|
||||
c->enum_type_table.put(bare_name, enum_type);
|
||||
c->decl_table.put(enum_decl, enum_type);
|
||||
|
||||
@ -847,22 +830,8 @@ static void visit_enum_decl(Context *c, const EnumDecl *enum_decl) {
|
||||
|
||||
Buf *bare_name = buf_create_from_str(decl_name(enum_decl));
|
||||
|
||||
if (enum_type->id == TypeTableEntryIdEnum) {
|
||||
if (enum_type->data.enumeration.complete) {
|
||||
Tld *tld = add_container_tld(c, enum_type);
|
||||
add_global_weak_alias(c, bare_name, tld);
|
||||
} else {
|
||||
TypeTableEntry *typedecl_type = get_typedecl_type(c->codegen, buf_ptr(&enum_type->name),
|
||||
c->codegen->builtin_types.entry_u8);
|
||||
Tld *tld = add_typedef_tld(c, typedecl_type);
|
||||
add_global_weak_alias(c, bare_name, tld);
|
||||
}
|
||||
} else if (enum_type->id == TypeTableEntryIdTypeDecl) {
|
||||
Tld *tld = add_typedef_tld(c, enum_type);
|
||||
add_global_weak_alias(c, bare_name, tld);
|
||||
} else {
|
||||
zig_unreachable();
|
||||
}
|
||||
Tld *tld = add_container_tld(c, enum_type);
|
||||
add_global_weak_alias(c, bare_name, tld);
|
||||
}
|
||||
|
||||
static TypeTableEntry *resolve_record_decl(Context *c, const RecordDecl *record_decl) {
|
||||
@ -912,7 +881,7 @@ static TypeTableEntry *resolve_record_decl(Context *c, const RecordDecl *record_
|
||||
const FieldDecl *field_decl = *it;
|
||||
|
||||
if (field_decl->isBitField()) {
|
||||
emit_warning(c, field_decl, "struct %s demoted to typedef - has bitfield\n", buf_ptr(bare_name));
|
||||
emit_warning(c, field_decl, "struct %s demoted to opaque type - has bitfield\n", buf_ptr(bare_name));
|
||||
replace_with_fwd_decl(c, struct_type, full_type_name);
|
||||
return struct_type;
|
||||
}
|
||||
@ -939,7 +908,7 @@ static TypeTableEntry *resolve_record_decl(Context *c, const RecordDecl *record_
|
||||
type_struct_field->type_entry = field_type;
|
||||
|
||||
if (type_is_invalid(field_type) || !type_is_complete(field_type)) {
|
||||
emit_warning(c, field_decl, "struct %s demoted to typedef - unresolved type\n", buf_ptr(bare_name));
|
||||
emit_warning(c, field_decl, "struct %s demoted to opaque type - unresolved type\n", buf_ptr(bare_name));
|
||||
replace_with_fwd_decl(c, struct_type, full_type_name);
|
||||
return struct_type;
|
||||
}
|
||||
@ -1001,23 +970,14 @@ static void visit_record_decl(Context *c, const RecordDecl *record_decl) {
|
||||
return;
|
||||
}
|
||||
|
||||
assert(struct_type->id == TypeTableEntryIdStruct);
|
||||
|
||||
bool is_anonymous = (record_decl->isAnonymousStructOrUnion() || decl_name(record_decl)[0] == 0);
|
||||
if (is_anonymous)
|
||||
return;
|
||||
|
||||
Buf *bare_name = buf_create_from_str(decl_name(record_decl));
|
||||
|
||||
if (struct_type->data.structure.complete) {
|
||||
Tld *tld = add_container_tld(c, struct_type);
|
||||
add_global_weak_alias(c, bare_name, tld);
|
||||
} else {
|
||||
TypeTableEntry *typedecl_type = get_typedecl_type(c->codegen, buf_ptr(&struct_type->name),
|
||||
c->codegen->builtin_types.entry_u8);
|
||||
Tld *tld = add_typedef_tld(c, typedecl_type);
|
||||
add_global_weak_alias(c, bare_name, tld);
|
||||
}
|
||||
Tld *tld = add_container_tld(c, struct_type);
|
||||
add_global_weak_alias(c, bare_name, tld);
|
||||
}
|
||||
|
||||
static void visit_var_decl(Context *c, const VarDecl *var_decl) {
|
||||
@ -1059,8 +1019,7 @@ static void visit_var_decl(Context *c, const VarDecl *var_decl) {
|
||||
switch (ap_value->getKind()) {
|
||||
case APValue::Int:
|
||||
{
|
||||
TypeTableEntry *canon_type = get_underlying_type(var_type);
|
||||
if (canon_type->id != TypeTableEntryIdInt) {
|
||||
if (var_type->id != TypeTableEntryIdInt) {
|
||||
emit_warning(c, var_decl,
|
||||
"ignoring variable '%s' - int initializer for non int type\n", buf_ptr(name));
|
||||
return;
|
||||
|
@ -710,7 +710,7 @@ static AstNode *ast_parse_try_expr(ParseContext *pc, size_t *token_index, bool m
|
||||
|
||||
/*
|
||||
PrimaryExpression = Number | String | CharLiteral | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | (option("extern") FnProto) | AsmExpression | ("error" "." Symbol) | ContainerDecl
|
||||
KeywordLiteral = "true" | "false" | "null" | "break" | "continue" | "undefined" | "error" | "type" | "this" | "unreachable"
|
||||
KeywordLiteral = "true" | "false" | "null" | "break" | "continue" | "undefined" | "error" | "this" | "unreachable"
|
||||
*/
|
||||
static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bool mandatory) {
|
||||
Token *token = &pc->tokens->at(*token_index);
|
||||
@ -766,10 +766,6 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bo
|
||||
AstNode *node = ast_create_node(pc, NodeTypeUnreachable, token);
|
||||
*token_index += 1;
|
||||
return node;
|
||||
} else if (token->id == TokenIdKeywordType) {
|
||||
AstNode *node = ast_create_node(pc, NodeTypeTypeLiteral, token);
|
||||
*token_index += 1;
|
||||
return node;
|
||||
} else if (token->id == TokenIdKeywordError) {
|
||||
AstNode *node = ast_create_node(pc, NodeTypeErrorType, token);
|
||||
*token_index += 1;
|
||||
@ -2500,34 +2496,9 @@ static AstNode *ast_parse_test_decl_node(ParseContext *pc, size_t *token_index)
|
||||
return node;
|
||||
}
|
||||
|
||||
/*
|
||||
TypeDecl = "type" "Symbol" "=" TypeExpr ";"
|
||||
*/
|
||||
static AstNode *ast_parse_type_decl(ParseContext *pc, size_t *token_index, VisibMod visib_mod) {
|
||||
Token *first_token = &pc->tokens->at(*token_index);
|
||||
|
||||
if (first_token->id != TokenIdKeywordType) {
|
||||
return nullptr;
|
||||
}
|
||||
*token_index += 1;
|
||||
|
||||
Token *name_tok = ast_eat_token(pc, token_index, TokenIdSymbol);
|
||||
ast_eat_token(pc, token_index, TokenIdEq);
|
||||
|
||||
AstNode *node = ast_create_node(pc, NodeTypeTypeDecl, first_token);
|
||||
node->data.type_decl.symbol = token_buf(name_tok);
|
||||
node->data.type_decl.child_type = ast_parse_type_expr(pc, token_index, true);
|
||||
|
||||
ast_eat_token(pc, token_index, TokenIdSemicolon);
|
||||
|
||||
node->data.type_decl.visib_mod = visib_mod;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
/*
|
||||
TopLevelItem = ErrorValueDecl | CompTimeExpression(Block) | TopLevelDecl | TestDecl
|
||||
TopLevelDecl = option(VisibleMod) (FnDef | ExternDecl | GlobalVarDecl | TypeDecl | UseDecl)
|
||||
TopLevelDecl = option(VisibleMod) (FnDef | ExternDecl | GlobalVarDecl | UseDecl)
|
||||
*/
|
||||
static void ast_parse_top_level_decls(ParseContext *pc, size_t *token_index, ZigList<AstNode *> *top_level_decls) {
|
||||
for (;;) {
|
||||
@ -2586,12 +2557,6 @@ static void ast_parse_top_level_decls(ParseContext *pc, size_t *token_index, Zig
|
||||
continue;
|
||||
}
|
||||
|
||||
AstNode *type_decl_node = ast_parse_type_decl(pc, token_index, visib_mod);
|
||||
if (type_decl_node) {
|
||||
top_level_decls->append(type_decl_node);
|
||||
continue;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
zig_unreachable();
|
||||
@ -2674,9 +2639,6 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
|
||||
visit_field(&node->data.variable_declaration.type, visit, context);
|
||||
visit_field(&node->data.variable_declaration.expr, visit, context);
|
||||
break;
|
||||
case NodeTypeTypeDecl:
|
||||
visit_field(&node->data.type_decl.child_type, visit, context);
|
||||
break;
|
||||
case NodeTypeErrorValueDecl:
|
||||
// none
|
||||
break;
|
||||
@ -2826,9 +2788,6 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
|
||||
case NodeTypeErrorType:
|
||||
// none
|
||||
break;
|
||||
case NodeTypeTypeLiteral:
|
||||
// none
|
||||
break;
|
||||
case NodeTypeVarLiteral:
|
||||
// none
|
||||
break;
|
||||
|
@ -139,7 +139,6 @@ static const struct ZigKeyword zig_keywords[] = {
|
||||
{"this", TokenIdKeywordThis},
|
||||
{"true", TokenIdKeywordTrue},
|
||||
{"try", TokenIdKeywordTry},
|
||||
{"type", TokenIdKeywordType},
|
||||
{"undefined", TokenIdKeywordUndefined},
|
||||
{"union", TokenIdKeywordUnion},
|
||||
{"unreachable", TokenIdKeywordUnreachable},
|
||||
@ -1474,7 +1473,6 @@ const char * token_name(TokenId id) {
|
||||
case TokenIdKeywordThis: return "this";
|
||||
case TokenIdKeywordTrue: return "true";
|
||||
case TokenIdKeywordTry: return "try";
|
||||
case TokenIdKeywordType: return "type";
|
||||
case TokenIdKeywordUndefined: return "undefined";
|
||||
case TokenIdKeywordUnion: return "union";
|
||||
case TokenIdKeywordUnreachable: return "unreachable";
|
||||
|
@ -76,7 +76,6 @@ enum TokenId {
|
||||
TokenIdKeywordThis,
|
||||
TokenIdKeywordTrue,
|
||||
TokenIdKeywordTry,
|
||||
TokenIdKeywordType,
|
||||
TokenIdKeywordUndefined,
|
||||
TokenIdKeywordUnion,
|
||||
TokenIdKeywordUnreachable,
|
||||
|
@ -1,10 +0,0 @@
|
||||
const assert = @import("std").debug.assert;
|
||||
|
||||
type int = u8;
|
||||
|
||||
fn add(a: int, b: int) -> int {
|
||||
a + b
|
||||
}
|
||||
test "typedef" {
|
||||
assert(add(12, 34) == 46);
|
||||
}
|
@ -2191,7 +2191,7 @@ struct Foo {
|
||||
add_parseh_case("struct prototype used in func", AllowWarningsNo, R"SOURCE(
|
||||
struct Foo;
|
||||
struct Foo *some_func(struct Foo *foo, int x);
|
||||
)SOURCE", 3, R"OUTPUT(pub type struct_Foo = u8;)OUTPUT",
|
||||
)SOURCE", 3, R"OUTPUT(pub const struct_Foo = @OpaqueType();)OUTPUT",
|
||||
R"OUTPUT(pub extern fn some_func(foo: ?&struct_Foo, x: c_int) -> ?&struct_Foo;)OUTPUT",
|
||||
R"OUTPUT(pub const Foo = struct_Foo;)OUTPUT");
|
||||
|
||||
@ -2277,12 +2277,12 @@ void foo(void (__cdecl *fn_ptr)(void));
|
||||
)SOURCE", 1, "pub const SDL_INIT_VIDEO = 32;");
|
||||
|
||||
add_parseh_case("zig keywords in C code", AllowWarningsNo, R"SOURCE(
|
||||
struct type {
|
||||
struct comptime {
|
||||
int defer;
|
||||
};
|
||||
)SOURCE", 2, R"(pub const struct_type = extern struct {
|
||||
)SOURCE", 2, R"(pub const struct_comptime = extern struct {
|
||||
@"defer": c_int,
|
||||
};)", R"(pub const @"type" = struct_type;)");
|
||||
};)", R"(pub const @"comptime" = struct_comptime;)");
|
||||
|
||||
add_parseh_case("macro defines string literal with octal", AllowWarningsNo, R"SOURCE(
|
||||
#define FOO "aoeu\023 derp"
|
||||
|
@ -31,7 +31,6 @@ comptime {
|
||||
_ = @import("cases/switch_prong_implicit_cast.zig");
|
||||
_ = @import("cases/this.zig");
|
||||
_ = @import("cases/try.zig");
|
||||
_ = @import("cases/typedef.zig");
|
||||
_ = @import("cases/undefined.zig");
|
||||
_ = @import("cases/var_args.zig");
|
||||
_ = @import("cases/void.zig");
|
||||
|
Loading…
Reference in New Issue
Block a user