IR: support import builtin function

master
Andrew Kelley 2016-11-26 20:52:22 -05:00
parent 4619b5de06
commit 84f7805029
9 changed files with 422 additions and 1085 deletions

View File

@ -117,12 +117,6 @@ enum ReturnKnowledge {
ReturnKnowledgeSkipDefers, ReturnKnowledgeSkipDefers,
}; };
struct Expr {
IrInstruction *instruction;
ReturnKnowledge return_knowledge;
VariableTableEntry *variable;
};
struct StructValExprCodeGen { struct StructValExprCodeGen {
TypeTableEntry *type_entry; TypeTableEntry *type_entry;
LLVMValueRef ptr; LLVMValueRef ptr;
@ -152,6 +146,7 @@ struct TopLevelDecl {
bool dep_loop_flag; bool dep_loop_flag;
TldResolution resolution; TldResolution resolution;
AstNode *parent_decl; AstNode *parent_decl;
IrInstruction *value;
}; };
struct TypeEnumField { struct TypeEnumField {
@ -232,7 +227,6 @@ struct AstNodeFnProto {
AstNode *fn_def_node; AstNode *fn_def_node;
FnTableEntry *fn_table_entry; FnTableEntry *fn_table_entry;
bool skip; bool skip;
Expr resolved_expr;
// computed from params field // computed from params field
size_t inline_arg_count; size_t inline_arg_count;
size_t inline_or_var_type_arg_count; size_t inline_or_var_type_arg_count;
@ -274,7 +268,6 @@ struct AstNodeBlock {
// you can follow its parents up to child_block. it will equal // you can follow its parents up to child_block. it will equal
// child_block if there are no defers or var decls in the block. // child_block if there are no defers or var decls in the block.
BlockContext *nested_block; BlockContext *nested_block;
Expr resolved_expr;
}; };
enum ReturnKind { enum ReturnKind {
@ -287,9 +280,6 @@ struct AstNodeReturnExpr {
ReturnKind kind; ReturnKind kind;
// might be null in case of return void; // might be null in case of return void;
AstNode *expr; AstNode *expr;
// populated by semantic analyzer:
Expr resolved_expr;
}; };
struct AstNodeDefer { struct AstNodeDefer {
@ -297,7 +287,6 @@ struct AstNodeDefer {
AstNode *expr; AstNode *expr;
// populated by semantic analyzer: // populated by semantic analyzer:
Expr resolved_expr;
size_t index_in_block; size_t index_in_block;
LLVMBasicBlockRef basic_block; LLVMBasicBlockRef basic_block;
BlockContext *child_block; BlockContext *child_block;
@ -314,7 +303,6 @@ struct AstNodeVariableDeclaration {
AstNode *expr; AstNode *expr;
// populated by semantic analyzer // populated by semantic analyzer
Expr resolved_expr;
VariableTableEntry *variable; VariableTableEntry *variable;
}; };
@ -392,7 +380,6 @@ struct AstNodeBinOpExpr {
// populated by semantic analyzer: // populated by semantic analyzer:
// for when op is BinOpTypeAssign // for when op is BinOpTypeAssign
VariableTableEntry *var_entry; VariableTableEntry *var_entry;
Expr resolved_expr;
}; };
struct AstNodeUnwrapErrorExpr { struct AstNodeUnwrapErrorExpr {
@ -401,7 +388,6 @@ struct AstNodeUnwrapErrorExpr {
AstNode *op2; AstNode *op2;
// populated by semantic analyzer: // populated by semantic analyzer:
Expr resolved_expr;
VariableTableEntry *var; VariableTableEntry *var;
}; };
@ -434,7 +420,6 @@ struct AstNodeFnCallExpr {
// populated by semantic analyzer: // populated by semantic analyzer:
BuiltinFnEntry *builtin_fn; BuiltinFnEntry *builtin_fn;
Expr resolved_expr;
FnTableEntry *fn_entry; FnTableEntry *fn_entry;
CastOp cast_op; CastOp cast_op;
// if cast_op is CastOpArrayToString, this will be a pointer to // if cast_op is CastOpArrayToString, this will be a pointer to
@ -447,7 +432,6 @@ struct AstNodeArrayAccessExpr {
AstNode *subscript; AstNode *subscript;
// populated by semantic analyzer: // populated by semantic analyzer:
Expr resolved_expr;
}; };
struct AstNodeSliceExpr { struct AstNodeSliceExpr {
@ -457,7 +441,6 @@ struct AstNodeSliceExpr {
bool is_const; bool is_const;
// populated by semantic analyzer: // populated by semantic analyzer:
Expr resolved_expr;
StructValExprCodeGen resolved_struct_val_expr; StructValExprCodeGen resolved_struct_val_expr;
}; };
@ -468,7 +451,6 @@ struct AstNodeFieldAccessExpr {
// populated by semantic analyzer // populated by semantic analyzer
TypeStructField *type_struct_field; TypeStructField *type_struct_field;
TypeEnumField *type_enum_field; TypeEnumField *type_enum_field;
Expr resolved_expr;
StructValExprCodeGen resolved_struct_val_expr; // for enum values StructValExprCodeGen resolved_struct_val_expr; // for enum values
TypeTableEntry *bare_container_type; TypeTableEntry *bare_container_type;
bool is_member_fn; bool is_member_fn;
@ -495,7 +477,6 @@ struct AstNodePrefixOpExpr {
AstNode *primary_expr; AstNode *primary_expr;
// populated by semantic analyzer // populated by semantic analyzer
Expr resolved_expr;
}; };
struct AstNodeUse { struct AstNodeUse {
@ -511,7 +492,6 @@ struct AstNodeIfBoolExpr {
AstNode *else_node; // null, block node, or other if expr node AstNode *else_node; // null, block node, or other if expr node
// populated by semantic analyzer // populated by semantic analyzer
Expr resolved_expr;
}; };
struct AstNodeIfVarExpr { struct AstNodeIfVarExpr {
@ -522,7 +502,6 @@ struct AstNodeIfVarExpr {
// populated by semantic analyzer // populated by semantic analyzer
TypeTableEntry *type; TypeTableEntry *type;
Expr resolved_expr;
}; };
struct AstNodeWhileExpr { struct AstNodeWhileExpr {
@ -535,7 +514,6 @@ struct AstNodeWhileExpr {
bool condition_always_true; bool condition_always_true;
bool contains_break; bool contains_break;
bool contains_continue; bool contains_continue;
Expr resolved_expr;
}; };
struct AstNodeForExpr { struct AstNodeForExpr {
@ -549,7 +527,6 @@ struct AstNodeForExpr {
// populated by semantic analyzer // populated by semantic analyzer
bool contains_break; bool contains_break;
bool contains_continue; bool contains_continue;
Expr resolved_expr;
VariableTableEntry *elem_var; VariableTableEntry *elem_var;
VariableTableEntry *index_var; VariableTableEntry *index_var;
}; };
@ -560,7 +537,6 @@ struct AstNodeSwitchExpr {
bool is_inline; bool is_inline;
// populated by semantic analyzer // populated by semantic analyzer
Expr resolved_expr;
}; };
struct AstNodeSwitchProng { struct AstNodeSwitchProng {
@ -580,7 +556,6 @@ struct AstNodeLabel {
Buf *name; Buf *name;
// populated by semantic analyzer // populated by semantic analyzer
Expr resolved_expr;
LabelTableEntry *label_entry; LabelTableEntry *label_entry;
}; };
@ -588,7 +563,6 @@ struct AstNodeGoto {
Buf *name; Buf *name;
// populated by semantic analyzer // populated by semantic analyzer
Expr resolved_expr;
LabelTableEntry *label_entry; LabelTableEntry *label_entry;
}; };
@ -634,7 +608,6 @@ struct AstNodeAsmExpr {
ZigList<Buf*> clobber_list; ZigList<Buf*> clobber_list;
// populated by semantic analyzer // populated by semantic analyzer
Expr resolved_expr;
}; };
enum ContainerKind { enum ContainerKind {
@ -670,14 +643,12 @@ struct AstNodeStringLiteral {
bool c; bool c;
// populated by semantic analyzer: // populated by semantic analyzer:
Expr resolved_expr;
}; };
struct AstNodeCharLiteral { struct AstNodeCharLiteral {
uint8_t value; uint8_t value;
// populated by semantic analyzer: // populated by semantic analyzer:
Expr resolved_expr;
}; };
struct AstNodeNumberLiteral { struct AstNodeNumberLiteral {
@ -688,7 +659,6 @@ struct AstNodeNumberLiteral {
bool overflow; bool overflow;
// populated by semantic analyzer // populated by semantic analyzer
Expr resolved_expr;
}; };
struct AstNodeStructValueField { struct AstNodeStructValueField {
@ -711,35 +681,29 @@ struct AstNodeContainerInitExpr {
// populated by semantic analyzer // populated by semantic analyzer
StructValExprCodeGen resolved_struct_val_expr; StructValExprCodeGen resolved_struct_val_expr;
Expr resolved_expr;
TypeTableEntry *enum_type; TypeTableEntry *enum_type;
}; };
struct AstNodeNullLiteral { struct AstNodeNullLiteral {
// populated by semantic analyzer // populated by semantic analyzer
Expr resolved_expr;
}; };
struct AstNodeUndefinedLiteral { struct AstNodeUndefinedLiteral {
// populated by semantic analyzer // populated by semantic analyzer
Expr resolved_expr;
}; };
struct AstNodeZeroesLiteral { struct AstNodeZeroesLiteral {
// populated by semantic analyzer // populated by semantic analyzer
Expr resolved_expr;
}; };
struct AstNodeThisLiteral { struct AstNodeThisLiteral {
// populated by semantic analyzer // populated by semantic analyzer
Expr resolved_expr;
}; };
struct AstNodeSymbolExpr { struct AstNodeSymbolExpr {
Buf *symbol; Buf *symbol;
// populated by semantic analyzer // populated by semantic analyzer
Expr resolved_expr;
TypeEnumField *enum_field; TypeEnumField *enum_field;
uint32_t err_value; uint32_t err_value;
}; };
@ -748,17 +712,14 @@ struct AstNodeBoolLiteral {
bool value; bool value;
// populated by semantic analyzer // populated by semantic analyzer
Expr resolved_expr;
}; };
struct AstNodeBreakExpr { struct AstNodeBreakExpr {
// populated by semantic analyzer // populated by semantic analyzer
Expr resolved_expr;
}; };
struct AstNodeContinueExpr { struct AstNodeContinueExpr {
// populated by semantic analyzer // populated by semantic analyzer
Expr resolved_expr;
}; };
struct AstNodeArrayType { struct AstNodeArrayType {
@ -767,22 +728,18 @@ struct AstNodeArrayType {
bool is_const; bool is_const;
// populated by semantic analyzer // populated by semantic analyzer
Expr resolved_expr;
}; };
struct AstNodeErrorType { struct AstNodeErrorType {
// populated by semantic analyzer // populated by semantic analyzer
Expr resolved_expr;
}; };
struct AstNodeTypeLiteral { struct AstNodeTypeLiteral {
// populated by semantic analyzer // populated by semantic analyzer
Expr resolved_expr;
}; };
struct AstNodeVarLiteral { struct AstNodeVarLiteral {
// populated by semantic analyzer // populated by semantic analyzer
Expr resolved_expr;
}; };
struct AstNode { struct AstNode {
@ -1329,7 +1286,6 @@ struct CodeGen {
LLVMValueRef err_name_table; LLVMValueRef err_name_table;
IrInstruction *invalid_instruction; IrInstruction *invalid_instruction;
Buf *len_buf;
}; };
struct VariableTableEntry { struct VariableTableEntry {
@ -1389,9 +1345,6 @@ struct BlockContext {
ZigLLVMDIScope *di_scope; ZigLLVMDIScope *di_scope;
Buf *c_import_buf; Buf *c_import_buf;
// if this is true, then this code will not be generated
bool codegen_excluded;
bool safety_off; bool safety_off;
AstNode *safety_set_node; AstNode *safety_set_node;
}; };
@ -1433,7 +1386,6 @@ enum IrInstructionId {
IrInstructionIdStorePtr, IrInstructionIdStorePtr,
IrInstructionIdFieldPtr, IrInstructionIdFieldPtr,
IrInstructionIdStructFieldPtr, IrInstructionIdStructFieldPtr,
IrInstructionIdReadField,
IrInstructionIdElemPtr, IrInstructionIdElemPtr,
IrInstructionIdVarPtr, IrInstructionIdVarPtr,
IrInstructionIdCall, IrInstructionIdCall,
@ -1460,6 +1412,8 @@ enum IrInstructionId {
IrInstructionIdClz, IrInstructionIdClz,
IrInstructionIdCtz, IrInstructionIdCtz,
IrInstructionIdStaticEval, IrInstructionIdStaticEval,
IrInstructionIdImport,
IrInstructionIdArrayLen,
}; };
struct IrInstruction { struct IrInstruction {
@ -1628,13 +1582,6 @@ struct IrInstructionStructFieldPtr {
bool is_const; bool is_const;
}; };
struct IrInstructionReadField {
IrInstruction base;
IrInstruction *container_ptr;
Buf *field_name;
};
struct IrInstructionElemPtr { struct IrInstructionElemPtr {
IrInstruction base; IrInstruction base;
@ -1816,6 +1763,18 @@ struct IrInstructionStaticEval {
IrInstruction *value; IrInstruction *value;
}; };
struct IrInstructionImport {
IrInstruction base;
IrInstruction *name;
};
struct IrInstructionArrayLen {
IrInstruction base;
IrInstruction *array_value;
};
enum LValPurpose { enum LValPurpose {
LValPurposeNone, LValPurposeNone,
LValPurposeAssign, LValPurposeAssign,

View File

@ -19,7 +19,6 @@
static void resolve_enum_type(CodeGen *g, ImportTableEntry *import, TypeTableEntry *enum_type); static void resolve_enum_type(CodeGen *g, ImportTableEntry *import, TypeTableEntry *enum_type);
static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableEntry *struct_type); static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableEntry *struct_type);
static void scan_decls(CodeGen *g, ImportTableEntry *import, BlockContext *context, AstNode *node);
AstNode *first_executing_node(AstNode *node) { AstNode *first_executing_node(AstNode *node) {
switch (node->type) { switch (node->type) {
@ -1670,7 +1669,7 @@ static void preview_error_value_decl(CodeGen *g, AstNode *node) {
node->data.error_value_decl.top_level_decl.resolution = TldResolutionOk; node->data.error_value_decl.top_level_decl.resolution = TldResolutionOk;
} }
static void scan_decls(CodeGen *g, ImportTableEntry *import, BlockContext *context, AstNode *node) { void scan_decls(CodeGen *g, ImportTableEntry *import, BlockContext *context, AstNode *node) {
switch (node->type) { switch (node->type) {
case NodeTypeRoot: case NodeTypeRoot:
for (size_t i = 0; i < import->root->data.root.top_level_decls.length; i += 1) { for (size_t i = 0; i < import->root->data.root.top_level_decls.length; i += 1) {
@ -1947,9 +1946,8 @@ static void resolve_var_decl(CodeGen *g, ImportTableEntry *import, AstNode *node
implicit_type = g->builtin_types.entry_invalid; implicit_type = g->builtin_types.entry_invalid;
} }
if (implicit_type->id != TypeTableEntryIdInvalid) { if (implicit_type->id != TypeTableEntryIdInvalid) {
Expr *expr = get_resolved_expr(var_decl->expr);
assert(result->static_value.special != ConstValSpecialRuntime); assert(result->static_value.special != ConstValSpecialRuntime);
expr->instruction = result; var_decl->top_level_decl.value = result;
} }
} else if (!is_extern) { } else if (!is_extern) {
add_node_error(g, node, buf_sprintf("variables must be initialized")); add_node_error(g, node, buf_sprintf("variables must be initialized"));
@ -2206,7 +2204,6 @@ BlockContext *new_block_context(AstNode *node, BlockContext *parent) {
if (parent) { if (parent) {
context->parent_loop_node = parent->parent_loop_node; context->parent_loop_node = parent->parent_loop_node;
context->c_import_buf = parent->c_import_buf; context->c_import_buf = parent->c_import_buf;
context->codegen_excluded = parent->codegen_excluded;
} }
if (node && node->type == NodeTypeFnDef) { if (node && node->type == NodeTypeFnDef) {
@ -2455,17 +2452,16 @@ static void analyze_fn_body(CodeGen *g, FnTableEntry *fn_table_entry) {
static void add_symbols_from_import(CodeGen *g, AstNode *src_use_node, AstNode *dst_use_node) { static void add_symbols_from_import(CodeGen *g, AstNode *src_use_node, AstNode *dst_use_node) {
TopLevelDecl *tld = get_as_top_level_decl(dst_use_node); TopLevelDecl *tld = get_as_top_level_decl(dst_use_node);
AstNode *use_target_node = src_use_node->data.use.expr;
Expr *expr = get_resolved_expr(use_target_node);
if (expr->instruction->type_entry->id == TypeTableEntryIdInvalid) { IrInstruction *use_target_value = tld->value;
if (use_target_value->type_entry->id == TypeTableEntryIdInvalid) {
tld->import->any_imports_failed = true; tld->import->any_imports_failed = true;
return; return;
} }
tld->resolution = TldResolutionOk; tld->resolution = TldResolutionOk;
ConstExprValue *const_val = &expr->instruction->static_value; ConstExprValue *const_val = &use_target_value->static_value;
assert(const_val->special != ConstValSpecialRuntime); assert(const_val->special != ConstValSpecialRuntime);
ImportTableEntry *target_import = const_val->data.x_import; ImportTableEntry *target_import = const_val->data.x_import;
@ -2511,7 +2507,7 @@ static void add_symbols_from_import(CodeGen *g, AstNode *src_use_node, AstNode *
} }
static void resolve_use_decl(CodeGen *g, AstNode *node) { void resolve_use_decl(CodeGen *g, AstNode *node) {
assert(node->type == NodeTypeUse); assert(node->type == NodeTypeUse);
if (get_as_top_level_decl(node)->resolution != TldResolutionUnresolved) { if (get_as_top_level_decl(node)->resolution != TldResolutionUnresolved) {
return; return;
@ -2519,7 +2515,7 @@ static void resolve_use_decl(CodeGen *g, AstNode *node) {
add_symbols_from_import(g, node, node); add_symbols_from_import(g, node, node);
} }
static void preview_use_decl(CodeGen *g, AstNode *node) { void preview_use_decl(CodeGen *g, AstNode *node) {
assert(node->type == NodeTypeUse); assert(node->type == NodeTypeUse);
TopLevelDecl *tld = get_as_top_level_decl(node); TopLevelDecl *tld = get_as_top_level_decl(node);
@ -2637,97 +2633,6 @@ void semantic_analyze(CodeGen *g) {
} }
} }
Expr *get_resolved_expr(AstNode *node) {
switch (node->type) {
case NodeTypeReturnExpr:
return &node->data.return_expr.resolved_expr;
case NodeTypeDefer:
return &node->data.defer.resolved_expr;
case NodeTypeBinOpExpr:
return &node->data.bin_op_expr.resolved_expr;
case NodeTypeUnwrapErrorExpr:
return &node->data.unwrap_err_expr.resolved_expr;
case NodeTypePrefixOpExpr:
return &node->data.prefix_op_expr.resolved_expr;
case NodeTypeFnCallExpr:
return &node->data.fn_call_expr.resolved_expr;
case NodeTypeArrayAccessExpr:
return &node->data.array_access_expr.resolved_expr;
case NodeTypeSliceExpr:
return &node->data.slice_expr.resolved_expr;
case NodeTypeFieldAccessExpr:
return &node->data.field_access_expr.resolved_expr;
case NodeTypeIfBoolExpr:
return &node->data.if_bool_expr.resolved_expr;
case NodeTypeIfVarExpr:
return &node->data.if_var_expr.resolved_expr;
case NodeTypeWhileExpr:
return &node->data.while_expr.resolved_expr;
case NodeTypeForExpr:
return &node->data.for_expr.resolved_expr;
case NodeTypeAsmExpr:
return &node->data.asm_expr.resolved_expr;
case NodeTypeContainerInitExpr:
return &node->data.container_init_expr.resolved_expr;
case NodeTypeNumberLiteral:
return &node->data.number_literal.resolved_expr;
case NodeTypeStringLiteral:
return &node->data.string_literal.resolved_expr;
case NodeTypeBlock:
return &node->data.block.resolved_expr;
case NodeTypeSymbol:
return &node->data.symbol_expr.resolved_expr;
case NodeTypeVariableDeclaration:
return &node->data.variable_declaration.resolved_expr;
case NodeTypeCharLiteral:
return &node->data.char_literal.resolved_expr;
case NodeTypeBoolLiteral:
return &node->data.bool_literal.resolved_expr;
case NodeTypeNullLiteral:
return &node->data.null_literal.resolved_expr;
case NodeTypeUndefinedLiteral:
return &node->data.undefined_literal.resolved_expr;
case NodeTypeZeroesLiteral:
return &node->data.zeroes_literal.resolved_expr;
case NodeTypeThisLiteral:
return &node->data.this_literal.resolved_expr;
case NodeTypeGoto:
return &node->data.goto_expr.resolved_expr;
case NodeTypeBreak:
return &node->data.break_expr.resolved_expr;
case NodeTypeContinue:
return &node->data.continue_expr.resolved_expr;
case NodeTypeLabel:
return &node->data.label.resolved_expr;
case NodeTypeArrayType:
return &node->data.array_type.resolved_expr;
case NodeTypeErrorType:
return &node->data.error_type.resolved_expr;
case NodeTypeTypeLiteral:
return &node->data.type_literal.resolved_expr;
case NodeTypeSwitchExpr:
return &node->data.switch_expr.resolved_expr;
case NodeTypeFnProto:
return &node->data.fn_proto.resolved_expr;
case NodeTypeVarLiteral:
return &node->data.var_literal.resolved_expr;
case NodeTypeSwitchProng:
case NodeTypeSwitchRange:
case NodeTypeRoot:
case NodeTypeFnDef:
case NodeTypeFnDecl:
case NodeTypeParamDecl:
case NodeTypeUse:
case NodeTypeContainerDecl:
case NodeTypeStructField:
case NodeTypeStructValueField:
case NodeTypeErrorValueDecl:
case NodeTypeTypeDecl:
zig_unreachable();
}
zig_unreachable();
}
TopLevelDecl *get_as_top_level_decl(AstNode *node) { TopLevelDecl *get_as_top_level_decl(AstNode *node) {
switch (node->type) { switch (node->type) {
case NodeTypeVariableDeclaration: case NodeTypeVariableDeclaration:
@ -2997,40 +2902,42 @@ static uint32_t hash_const_val(TypeTableEntry *type, ConstExprValue *const_val)
} }
uint32_t generic_fn_type_id_hash(GenericFnTypeId *id) { uint32_t generic_fn_type_id_hash(GenericFnTypeId *id) {
uint32_t result = 0; zig_panic("TODO generic_fn_type_id_hash");
result += hash_ptr(id->decl_node); //uint32_t result = 0;
for (size_t i = 0; i < id->generic_param_count; i += 1) { //result += hash_ptr(id->decl_node);
GenericParamValue *generic_param = &id->generic_params[i]; //for (size_t i = 0; i < id->generic_param_count; i += 1) {
if (generic_param->node) { // GenericParamValue *generic_param = &id->generic_params[i];
ConstExprValue *const_val = &get_resolved_expr(generic_param->node)->instruction->static_value; // if (generic_param->node) {
assert(const_val->special != ConstValSpecialRuntime); // ConstExprValue *const_val = &get_resolved_expr(generic_param->node)->instruction->static_value;
result += hash_const_val(generic_param->type, const_val); // assert(const_val->special != ConstValSpecialRuntime);
} // result += hash_const_val(generic_param->type, const_val);
result += hash_ptr(generic_param->type); // }
} // result += hash_ptr(generic_param->type);
return result; //}
//return result;
} }
bool generic_fn_type_id_eql(GenericFnTypeId *a, GenericFnTypeId *b) { bool generic_fn_type_id_eql(GenericFnTypeId *a, GenericFnTypeId *b) {
if (a->decl_node != b->decl_node) return false; zig_panic("TODO generic_fn_type_id_eql");
assert(a->generic_param_count == b->generic_param_count); //if (a->decl_node != b->decl_node) return false;
for (size_t i = 0; i < a->generic_param_count; i += 1) { //assert(a->generic_param_count == b->generic_param_count);
GenericParamValue *a_val = &a->generic_params[i]; //for (size_t i = 0; i < a->generic_param_count; i += 1) {
GenericParamValue *b_val = &b->generic_params[i]; // GenericParamValue *a_val = &a->generic_params[i];
if (a_val->type != b_val->type) return false; // GenericParamValue *b_val = &b->generic_params[i];
if (a_val->node && b_val->node) { // if (a_val->type != b_val->type) return false;
ConstExprValue *a_const_val = &get_resolved_expr(a_val->node)->instruction->static_value; // if (a_val->node && b_val->node) {
ConstExprValue *b_const_val = &get_resolved_expr(b_val->node)->instruction->static_value; // ConstExprValue *a_const_val = &get_resolved_expr(a_val->node)->instruction->static_value;
assert(a_const_val->special != ConstValSpecialRuntime); // ConstExprValue *b_const_val = &get_resolved_expr(b_val->node)->instruction->static_value;
assert(b_const_val->special != ConstValSpecialRuntime); // assert(a_const_val->special != ConstValSpecialRuntime);
if (!const_values_equal(a_const_val, b_const_val, a_val->type)) { // assert(b_const_val->special != ConstValSpecialRuntime);
return false; // if (!const_values_equal(a_const_val, b_const_val, a_val->type)) {
} // return false;
} else { // }
assert(!a_val->node && !b_val->node); // } else {
} // assert(!a_val->node && !b_val->node);
} // }
return true; //}
//return true;
} }
bool type_has_bits(TypeTableEntry *type_entry) { bool type_has_bits(TypeTableEntry *type_entry) {
@ -3095,5 +3002,3 @@ uint64_t get_memcpy_align(CodeGen *g, TypeTableEntry *type_entry) {
TypeTableEntry *first_type_in_mem = type_of_first_thing_in_memory(type_entry); TypeTableEntry *first_type_in_mem = type_of_first_thing_in_memory(type_entry);
return LLVMABISizeOfType(g->target_data_ref, first_type_in_mem->type_ref); return LLVMABISizeOfType(g->target_data_ref, first_type_in_mem->type_ref);
} }

View File

@ -16,7 +16,6 @@ ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, AstNode *node, Buf *m
TypeTableEntry *new_type_table_entry(TypeTableEntryId id); TypeTableEntry *new_type_table_entry(TypeTableEntryId id);
TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const); TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const);
BlockContext *new_block_context(AstNode *node, BlockContext *parent); BlockContext *new_block_context(AstNode *node, BlockContext *parent);
Expr *get_resolved_expr(AstNode *node);
bool is_node_void_expr(AstNode *node); bool is_node_void_expr(AstNode *node);
uint64_t type_size(CodeGen *g, TypeTableEntry *type_entry); uint64_t type_size(CodeGen *g, TypeTableEntry *type_entry);
TypeTableEntry **get_int_type_ptr(CodeGen *g, bool is_signed, size_t size_in_bits); TypeTableEntry **get_int_type_ptr(CodeGen *g, bool is_signed, size_t size_in_bits);
@ -63,5 +62,8 @@ TypeStructField *find_struct_type_field(TypeTableEntry *type_entry, Buf *name);
BlockContext *get_container_block_context(TypeTableEntry *type_entry); BlockContext *get_container_block_context(TypeTableEntry *type_entry);
TypeEnumField *find_enum_type_field(TypeTableEntry *enum_type, Buf *name); TypeEnumField *find_enum_type_field(TypeTableEntry *enum_type, Buf *name);
bool is_container_ref(TypeTableEntry *type_entry); bool is_container_ref(TypeTableEntry *type_entry);
void scan_decls(CodeGen *g, ImportTableEntry *import, BlockContext *context, AstNode *node);
void preview_use_decl(CodeGen *g, AstNode *node);
void resolve_use_decl(CodeGen *g, AstNode *node);
#endif #endif

View File

@ -528,25 +528,24 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
break; break;
} }
case NodeTypeFnCallExpr: case NodeTypeFnCallExpr:
if (node->data.fn_call_expr.is_builtin) { {
fprintf(ar->f, "@"); if (node->data.fn_call_expr.is_builtin) {
} else { fprintf(ar->f, "@");
fprintf(ar->f, "(");
}
render_node_ungrouped(ar, node->data.fn_call_expr.fn_ref_expr);
if (!node->data.fn_call_expr.is_builtin) {
fprintf(ar->f, ")");
}
fprintf(ar->f, "(");
for (size_t i = 0; i < node->data.fn_call_expr.params.length; i += 1) {
AstNode *param = node->data.fn_call_expr.params.at(i);
if (i != 0) {
fprintf(ar->f, ", ");
} }
render_node_grouped(ar, param); AstNode *fn_ref_node = node->data.fn_call_expr.fn_ref_expr;
bool grouped = (fn_ref_node->type != NodeTypeBinOpExpr);
render_node_extra(ar, fn_ref_node, grouped);
fprintf(ar->f, "(");
for (size_t i = 0; i < node->data.fn_call_expr.params.length; i += 1) {
AstNode *param = node->data.fn_call_expr.params.at(i);
if (i != 0) {
fprintf(ar->f, ", ");
}
render_node_grouped(ar, param);
}
fprintf(ar->f, ")");
break;
} }
fprintf(ar->f, ")");
break;
case NodeTypeArrayAccessExpr: case NodeTypeArrayAccessExpr:
render_node_ungrouped(ar, node->data.array_access_expr.array_ref_expr); render_node_ungrouped(ar, node->data.array_access_expr.array_ref_expr);
fprintf(ar->f, "["); fprintf(ar->f, "[");

View File

@ -65,8 +65,6 @@ CodeGen *codegen_create(Buf *root_source_dir, const ZigTarget *target) {
g->is_test_build = false; g->is_test_build = false;
g->want_h_file = true; g->want_h_file = true;
g->len_buf = buf_create_from_str("len");
// the error.Ok value // the error.Ok value
g->error_decls.append(nullptr); g->error_decls.append(nullptr);
@ -1682,6 +1680,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
case IrInstructionIdSizeOf: case IrInstructionIdSizeOf:
case IrInstructionIdSwitchTarget: case IrInstructionIdSwitchTarget:
case IrInstructionIdStaticEval: case IrInstructionIdStaticEval:
case IrInstructionIdImport:
zig_unreachable(); zig_unreachable();
case IrInstructionIdReturn: case IrInstructionIdReturn:
return ir_render_return(g, executable, (IrInstructionReturn *)instruction); return ir_render_return(g, executable, (IrInstructionReturn *)instruction);
@ -1728,8 +1727,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
case IrInstructionIdSwitchVar: case IrInstructionIdSwitchVar:
case IrInstructionIdContainerInitList: case IrInstructionIdContainerInitList:
case IrInstructionIdContainerInitFields: case IrInstructionIdContainerInitFields:
case IrInstructionIdReadField:
case IrInstructionIdEnumTag: case IrInstructionIdEnumTag:
case IrInstructionIdArrayLen:
zig_panic("TODO render more IR instructions to LLVM"); zig_panic("TODO render more IR instructions to LLVM");
} }
zig_unreachable(); zig_unreachable();
@ -2114,7 +2113,7 @@ static void do_code_gen(CodeGen *g) {
if (var->type->id == TypeTableEntryIdNumLitFloat) { if (var->type->id == TypeTableEntryIdNumLitFloat) {
// Generate debug info for it but that's it. // Generate debug info for it but that's it.
ConstExprValue *const_val = &get_resolved_expr(var->val_node)->instruction->static_value; ConstExprValue *const_val = &var->decl_node->data.variable_declaration.top_level_decl.value->static_value;
assert(const_val->special != ConstValSpecialRuntime); assert(const_val->special != ConstValSpecialRuntime);
TypeTableEntry *var_type = g->builtin_types.entry_f64; TypeTableEntry *var_type = g->builtin_types.entry_f64;
LLVMValueRef init_val = LLVMConstReal(var_type->type_ref, const_val->data.x_bignum.data.x_float); LLVMValueRef init_val = LLVMConstReal(var_type->type_ref, const_val->data.x_bignum.data.x_float);
@ -2124,7 +2123,7 @@ static void do_code_gen(CodeGen *g) {
if (var->type->id == TypeTableEntryIdNumLitInt) { if (var->type->id == TypeTableEntryIdNumLitInt) {
// Generate debug info for it but that's it. // Generate debug info for it but that's it.
ConstExprValue *const_val = &get_resolved_expr(var->val_node)->instruction->static_value; ConstExprValue *const_val = &var->decl_node->data.variable_declaration.top_level_decl.value->static_value;
assert(const_val->special != ConstValSpecialRuntime); assert(const_val->special != ConstValSpecialRuntime);
TypeTableEntry *var_type = const_val->data.x_bignum.is_negative ? TypeTableEntry *var_type = const_val->data.x_bignum.is_negative ?
g->builtin_types.entry_isize : g->builtin_types.entry_usize; g->builtin_types.entry_isize : g->builtin_types.entry_usize;
@ -2149,8 +2148,7 @@ static void do_code_gen(CodeGen *g) {
LLVMSetLinkage(global_value, LLVMExternalLinkage); LLVMSetLinkage(global_value, LLVMExternalLinkage);
} else { } else {
AstNode *expr_node = var->decl_node->data.variable_declaration.expr; IrInstruction *instruction = var->decl_node->data.variable_declaration.top_level_decl.value;
IrInstruction *instruction = get_resolved_expr(expr_node)->instruction;
render_const_val(g, instruction->type_entry, &instruction->static_value); render_const_val(g, instruction->type_entry, &instruction->static_value);
render_const_val_global(g, instruction->type_entry, &instruction->static_value); render_const_val_global(g, instruction->type_entry, &instruction->static_value);
global_value = instruction->static_value.llvm_global; global_value = instruction->static_value.llvm_global;

1172
src/ir.cpp

File diff suppressed because it is too large Load Diff

View File

@ -115,6 +115,12 @@ static void ir_print_const_value(IrPrint *irp, TypeTableEntry *type_entry, Const
} }
break; break;
} }
case TypeTableEntryIdNamespace:
{
ImportTableEntry *import = const_val->data.x_import;
fprintf(irp->f, "(namespace: %s)", buf_ptr(import->path));
break;
}
case TypeTableEntryIdVar: case TypeTableEntryIdVar:
case TypeTableEntryIdFloat: case TypeTableEntryIdFloat:
case TypeTableEntryIdStruct: case TypeTableEntryIdStruct:
@ -124,7 +130,6 @@ static void ir_print_const_value(IrPrint *irp, TypeTableEntry *type_entry, Const
case TypeTableEntryIdEnum: case TypeTableEntryIdEnum:
case TypeTableEntryIdUnion: case TypeTableEntryIdUnion:
case TypeTableEntryIdTypeDecl: case TypeTableEntryIdTypeDecl:
case TypeTableEntryIdNamespace:
case TypeTableEntryIdGenericFn: case TypeTableEntryIdGenericFn:
zig_panic("TODO render more constant types in IR printer"); zig_panic("TODO render more constant types in IR printer");
} }
@ -407,11 +412,6 @@ static void ir_print_field_ptr(IrPrint *irp, IrInstructionFieldPtr *instruction)
fprintf(irp->f, ")"); fprintf(irp->f, ")");
} }
static void ir_print_read_field(IrPrint *irp, IrInstructionReadField *instruction) {
ir_print_other_instruction(irp, instruction->container_ptr);
fprintf(irp->f, ".%s", buf_ptr(instruction->field_name));
}
static void ir_print_struct_field_ptr(IrPrint *irp, IrInstructionStructFieldPtr *instruction) { static void ir_print_struct_field_ptr(IrPrint *irp, IrInstructionStructFieldPtr *instruction) {
fprintf(irp->f, "@StructFieldPtr(&"); fprintf(irp->f, "@StructFieldPtr(&");
ir_print_other_instruction(irp, instruction->struct_ptr); ir_print_other_instruction(irp, instruction->struct_ptr);
@ -575,6 +575,17 @@ static void ir_print_static_eval(IrPrint *irp, IrInstructionStaticEval *instruct
fprintf(irp->f, ")"); fprintf(irp->f, ")");
} }
static void ir_print_import(IrPrint *irp, IrInstructionImport *instruction) {
fprintf(irp->f, "@import(");
ir_print_other_instruction(irp, instruction->name);
fprintf(irp->f, ")");
}
static void ir_print_array_len(IrPrint *irp, IrInstructionArrayLen *instruction) {
ir_print_other_instruction(irp, instruction->array_value);
fprintf(irp->f, ".len");
}
static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
ir_print_prefix(irp, instruction); ir_print_prefix(irp, instruction);
switch (instruction->id) { switch (instruction->id) {
@ -643,9 +654,6 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdFieldPtr: case IrInstructionIdFieldPtr:
ir_print_field_ptr(irp, (IrInstructionFieldPtr *)instruction); ir_print_field_ptr(irp, (IrInstructionFieldPtr *)instruction);
break; break;
case IrInstructionIdReadField:
ir_print_read_field(irp, (IrInstructionReadField *)instruction);
break;
case IrInstructionIdStructFieldPtr: case IrInstructionIdStructFieldPtr:
ir_print_struct_field_ptr(irp, (IrInstructionStructFieldPtr *)instruction); ir_print_struct_field_ptr(irp, (IrInstructionStructFieldPtr *)instruction);
break; break;
@ -700,6 +708,12 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdStaticEval: case IrInstructionIdStaticEval:
ir_print_static_eval(irp, (IrInstructionStaticEval *)instruction); ir_print_static_eval(irp, (IrInstructionStaticEval *)instruction);
break; break;
case IrInstructionIdImport:
ir_print_import(irp, (IrInstructionImport *)instruction);
break;
case IrInstructionIdArrayLen:
ir_print_array_len(irp, (IrInstructionArrayLen *)instruction);
break;
} }
fprintf(irp->f, "\n"); fprintf(irp->f, "\n");
} }

View File

@ -0,0 +1 @@
pub fn foo() -> i32 { 1234 }

View File

@ -1,3 +1,5 @@
const case_namespace_fn_call = @import("cases/namespace_fn_call.zig");
pub const SYS_write = 1; pub const SYS_write = 1;
pub const SYS_exit = 60; pub const SYS_exit = 60;
pub const stdout_fileno = 1; pub const stdout_fileno = 1;
@ -61,6 +63,10 @@ fn testInlineSwitch() {
assert(result + 1 == 14); assert(result + 1 == 14);
} }
fn testNamespaceFnCall() {
assert(case_namespace_fn_call.foo() == 1234);
}
fn assert(ok: bool) { fn assert(ok: bool) {
if (!ok) if (!ok)
@unreachable(); @unreachable();
@ -73,6 +79,7 @@ fn runAllTests() {
switchWithNumbers(); switchWithNumbers();
switchWithAllRanges(); switchWithAllRanges();
testInlineSwitch(); testInlineSwitch();
testNamespaceFnCall();
} }
export nakedcc fn _start() -> unreachable { export nakedcc fn _start() -> unreachable {