IR: support import builtin function
parent
4619b5de06
commit
84f7805029
|
@ -117,12 +117,6 @@ enum ReturnKnowledge {
|
|||
ReturnKnowledgeSkipDefers,
|
||||
};
|
||||
|
||||
struct Expr {
|
||||
IrInstruction *instruction;
|
||||
ReturnKnowledge return_knowledge;
|
||||
VariableTableEntry *variable;
|
||||
};
|
||||
|
||||
struct StructValExprCodeGen {
|
||||
TypeTableEntry *type_entry;
|
||||
LLVMValueRef ptr;
|
||||
|
@ -152,6 +146,7 @@ struct TopLevelDecl {
|
|||
bool dep_loop_flag;
|
||||
TldResolution resolution;
|
||||
AstNode *parent_decl;
|
||||
IrInstruction *value;
|
||||
};
|
||||
|
||||
struct TypeEnumField {
|
||||
|
@ -232,7 +227,6 @@ struct AstNodeFnProto {
|
|||
AstNode *fn_def_node;
|
||||
FnTableEntry *fn_table_entry;
|
||||
bool skip;
|
||||
Expr resolved_expr;
|
||||
// computed from params field
|
||||
size_t inline_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
|
||||
// child_block if there are no defers or var decls in the block.
|
||||
BlockContext *nested_block;
|
||||
Expr resolved_expr;
|
||||
};
|
||||
|
||||
enum ReturnKind {
|
||||
|
@ -287,9 +280,6 @@ struct AstNodeReturnExpr {
|
|||
ReturnKind kind;
|
||||
// might be null in case of return void;
|
||||
AstNode *expr;
|
||||
|
||||
// populated by semantic analyzer:
|
||||
Expr resolved_expr;
|
||||
};
|
||||
|
||||
struct AstNodeDefer {
|
||||
|
@ -297,7 +287,6 @@ struct AstNodeDefer {
|
|||
AstNode *expr;
|
||||
|
||||
// populated by semantic analyzer:
|
||||
Expr resolved_expr;
|
||||
size_t index_in_block;
|
||||
LLVMBasicBlockRef basic_block;
|
||||
BlockContext *child_block;
|
||||
|
@ -314,7 +303,6 @@ struct AstNodeVariableDeclaration {
|
|||
AstNode *expr;
|
||||
|
||||
// populated by semantic analyzer
|
||||
Expr resolved_expr;
|
||||
VariableTableEntry *variable;
|
||||
};
|
||||
|
||||
|
@ -392,7 +380,6 @@ struct AstNodeBinOpExpr {
|
|||
// populated by semantic analyzer:
|
||||
// for when op is BinOpTypeAssign
|
||||
VariableTableEntry *var_entry;
|
||||
Expr resolved_expr;
|
||||
};
|
||||
|
||||
struct AstNodeUnwrapErrorExpr {
|
||||
|
@ -401,7 +388,6 @@ struct AstNodeUnwrapErrorExpr {
|
|||
AstNode *op2;
|
||||
|
||||
// populated by semantic analyzer:
|
||||
Expr resolved_expr;
|
||||
VariableTableEntry *var;
|
||||
};
|
||||
|
||||
|
@ -434,7 +420,6 @@ struct AstNodeFnCallExpr {
|
|||
|
||||
// populated by semantic analyzer:
|
||||
BuiltinFnEntry *builtin_fn;
|
||||
Expr resolved_expr;
|
||||
FnTableEntry *fn_entry;
|
||||
CastOp cast_op;
|
||||
// if cast_op is CastOpArrayToString, this will be a pointer to
|
||||
|
@ -447,7 +432,6 @@ struct AstNodeArrayAccessExpr {
|
|||
AstNode *subscript;
|
||||
|
||||
// populated by semantic analyzer:
|
||||
Expr resolved_expr;
|
||||
};
|
||||
|
||||
struct AstNodeSliceExpr {
|
||||
|
@ -457,7 +441,6 @@ struct AstNodeSliceExpr {
|
|||
bool is_const;
|
||||
|
||||
// populated by semantic analyzer:
|
||||
Expr resolved_expr;
|
||||
StructValExprCodeGen resolved_struct_val_expr;
|
||||
};
|
||||
|
||||
|
@ -468,7 +451,6 @@ struct AstNodeFieldAccessExpr {
|
|||
// populated by semantic analyzer
|
||||
TypeStructField *type_struct_field;
|
||||
TypeEnumField *type_enum_field;
|
||||
Expr resolved_expr;
|
||||
StructValExprCodeGen resolved_struct_val_expr; // for enum values
|
||||
TypeTableEntry *bare_container_type;
|
||||
bool is_member_fn;
|
||||
|
@ -495,7 +477,6 @@ struct AstNodePrefixOpExpr {
|
|||
AstNode *primary_expr;
|
||||
|
||||
// populated by semantic analyzer
|
||||
Expr resolved_expr;
|
||||
};
|
||||
|
||||
struct AstNodeUse {
|
||||
|
@ -511,7 +492,6 @@ struct AstNodeIfBoolExpr {
|
|||
AstNode *else_node; // null, block node, or other if expr node
|
||||
|
||||
// populated by semantic analyzer
|
||||
Expr resolved_expr;
|
||||
};
|
||||
|
||||
struct AstNodeIfVarExpr {
|
||||
|
@ -522,7 +502,6 @@ struct AstNodeIfVarExpr {
|
|||
|
||||
// populated by semantic analyzer
|
||||
TypeTableEntry *type;
|
||||
Expr resolved_expr;
|
||||
};
|
||||
|
||||
struct AstNodeWhileExpr {
|
||||
|
@ -535,7 +514,6 @@ struct AstNodeWhileExpr {
|
|||
bool condition_always_true;
|
||||
bool contains_break;
|
||||
bool contains_continue;
|
||||
Expr resolved_expr;
|
||||
};
|
||||
|
||||
struct AstNodeForExpr {
|
||||
|
@ -549,7 +527,6 @@ struct AstNodeForExpr {
|
|||
// populated by semantic analyzer
|
||||
bool contains_break;
|
||||
bool contains_continue;
|
||||
Expr resolved_expr;
|
||||
VariableTableEntry *elem_var;
|
||||
VariableTableEntry *index_var;
|
||||
};
|
||||
|
@ -560,7 +537,6 @@ struct AstNodeSwitchExpr {
|
|||
bool is_inline;
|
||||
|
||||
// populated by semantic analyzer
|
||||
Expr resolved_expr;
|
||||
};
|
||||
|
||||
struct AstNodeSwitchProng {
|
||||
|
@ -580,7 +556,6 @@ struct AstNodeLabel {
|
|||
Buf *name;
|
||||
|
||||
// populated by semantic analyzer
|
||||
Expr resolved_expr;
|
||||
LabelTableEntry *label_entry;
|
||||
};
|
||||
|
||||
|
@ -588,7 +563,6 @@ struct AstNodeGoto {
|
|||
Buf *name;
|
||||
|
||||
// populated by semantic analyzer
|
||||
Expr resolved_expr;
|
||||
LabelTableEntry *label_entry;
|
||||
};
|
||||
|
||||
|
@ -634,7 +608,6 @@ struct AstNodeAsmExpr {
|
|||
ZigList<Buf*> clobber_list;
|
||||
|
||||
// populated by semantic analyzer
|
||||
Expr resolved_expr;
|
||||
};
|
||||
|
||||
enum ContainerKind {
|
||||
|
@ -670,14 +643,12 @@ struct AstNodeStringLiteral {
|
|||
bool c;
|
||||
|
||||
// populated by semantic analyzer:
|
||||
Expr resolved_expr;
|
||||
};
|
||||
|
||||
struct AstNodeCharLiteral {
|
||||
uint8_t value;
|
||||
|
||||
// populated by semantic analyzer:
|
||||
Expr resolved_expr;
|
||||
};
|
||||
|
||||
struct AstNodeNumberLiteral {
|
||||
|
@ -688,7 +659,6 @@ struct AstNodeNumberLiteral {
|
|||
bool overflow;
|
||||
|
||||
// populated by semantic analyzer
|
||||
Expr resolved_expr;
|
||||
};
|
||||
|
||||
struct AstNodeStructValueField {
|
||||
|
@ -711,35 +681,29 @@ struct AstNodeContainerInitExpr {
|
|||
|
||||
// populated by semantic analyzer
|
||||
StructValExprCodeGen resolved_struct_val_expr;
|
||||
Expr resolved_expr;
|
||||
TypeTableEntry *enum_type;
|
||||
};
|
||||
|
||||
struct AstNodeNullLiteral {
|
||||
// populated by semantic analyzer
|
||||
Expr resolved_expr;
|
||||
};
|
||||
|
||||
struct AstNodeUndefinedLiteral {
|
||||
// populated by semantic analyzer
|
||||
Expr resolved_expr;
|
||||
};
|
||||
|
||||
struct AstNodeZeroesLiteral {
|
||||
// populated by semantic analyzer
|
||||
Expr resolved_expr;
|
||||
};
|
||||
|
||||
struct AstNodeThisLiteral {
|
||||
// populated by semantic analyzer
|
||||
Expr resolved_expr;
|
||||
};
|
||||
|
||||
struct AstNodeSymbolExpr {
|
||||
Buf *symbol;
|
||||
|
||||
// populated by semantic analyzer
|
||||
Expr resolved_expr;
|
||||
TypeEnumField *enum_field;
|
||||
uint32_t err_value;
|
||||
};
|
||||
|
@ -748,17 +712,14 @@ struct AstNodeBoolLiteral {
|
|||
bool value;
|
||||
|
||||
// populated by semantic analyzer
|
||||
Expr resolved_expr;
|
||||
};
|
||||
|
||||
struct AstNodeBreakExpr {
|
||||
// populated by semantic analyzer
|
||||
Expr resolved_expr;
|
||||
};
|
||||
|
||||
struct AstNodeContinueExpr {
|
||||
// populated by semantic analyzer
|
||||
Expr resolved_expr;
|
||||
};
|
||||
|
||||
struct AstNodeArrayType {
|
||||
|
@ -767,22 +728,18 @@ struct AstNodeArrayType {
|
|||
bool is_const;
|
||||
|
||||
// populated by semantic analyzer
|
||||
Expr resolved_expr;
|
||||
};
|
||||
|
||||
struct AstNodeErrorType {
|
||||
// populated by semantic analyzer
|
||||
Expr resolved_expr;
|
||||
};
|
||||
|
||||
struct AstNodeTypeLiteral {
|
||||
// populated by semantic analyzer
|
||||
Expr resolved_expr;
|
||||
};
|
||||
|
||||
struct AstNodeVarLiteral {
|
||||
// populated by semantic analyzer
|
||||
Expr resolved_expr;
|
||||
};
|
||||
|
||||
struct AstNode {
|
||||
|
@ -1329,7 +1286,6 @@ struct CodeGen {
|
|||
LLVMValueRef err_name_table;
|
||||
|
||||
IrInstruction *invalid_instruction;
|
||||
Buf *len_buf;
|
||||
};
|
||||
|
||||
struct VariableTableEntry {
|
||||
|
@ -1389,9 +1345,6 @@ struct BlockContext {
|
|||
ZigLLVMDIScope *di_scope;
|
||||
Buf *c_import_buf;
|
||||
|
||||
// if this is true, then this code will not be generated
|
||||
bool codegen_excluded;
|
||||
|
||||
bool safety_off;
|
||||
AstNode *safety_set_node;
|
||||
};
|
||||
|
@ -1433,7 +1386,6 @@ enum IrInstructionId {
|
|||
IrInstructionIdStorePtr,
|
||||
IrInstructionIdFieldPtr,
|
||||
IrInstructionIdStructFieldPtr,
|
||||
IrInstructionIdReadField,
|
||||
IrInstructionIdElemPtr,
|
||||
IrInstructionIdVarPtr,
|
||||
IrInstructionIdCall,
|
||||
|
@ -1460,6 +1412,8 @@ enum IrInstructionId {
|
|||
IrInstructionIdClz,
|
||||
IrInstructionIdCtz,
|
||||
IrInstructionIdStaticEval,
|
||||
IrInstructionIdImport,
|
||||
IrInstructionIdArrayLen,
|
||||
};
|
||||
|
||||
struct IrInstruction {
|
||||
|
@ -1628,13 +1582,6 @@ struct IrInstructionStructFieldPtr {
|
|||
bool is_const;
|
||||
};
|
||||
|
||||
struct IrInstructionReadField {
|
||||
IrInstruction base;
|
||||
|
||||
IrInstruction *container_ptr;
|
||||
Buf *field_name;
|
||||
};
|
||||
|
||||
struct IrInstructionElemPtr {
|
||||
IrInstruction base;
|
||||
|
||||
|
@ -1816,6 +1763,18 @@ struct IrInstructionStaticEval {
|
|||
IrInstruction *value;
|
||||
};
|
||||
|
||||
struct IrInstructionImport {
|
||||
IrInstruction base;
|
||||
|
||||
IrInstruction *name;
|
||||
};
|
||||
|
||||
struct IrInstructionArrayLen {
|
||||
IrInstruction base;
|
||||
|
||||
IrInstruction *array_value;
|
||||
};
|
||||
|
||||
enum LValPurpose {
|
||||
LValPurposeNone,
|
||||
LValPurposeAssign,
|
||||
|
|
175
src/analyze.cpp
175
src/analyze.cpp
|
@ -19,7 +19,6 @@
|
|||
|
||||
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 scan_decls(CodeGen *g, ImportTableEntry *import, BlockContext *context, AstNode *node);
|
||||
|
||||
AstNode *first_executing_node(AstNode *node) {
|
||||
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;
|
||||
}
|
||||
|
||||
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) {
|
||||
case NodeTypeRoot:
|
||||
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;
|
||||
}
|
||||
if (implicit_type->id != TypeTableEntryIdInvalid) {
|
||||
Expr *expr = get_resolved_expr(var_decl->expr);
|
||||
assert(result->static_value.special != ConstValSpecialRuntime);
|
||||
expr->instruction = result;
|
||||
var_decl->top_level_decl.value = result;
|
||||
}
|
||||
} else if (!is_extern) {
|
||||
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) {
|
||||
context->parent_loop_node = parent->parent_loop_node;
|
||||
context->c_import_buf = parent->c_import_buf;
|
||||
context->codegen_excluded = parent->codegen_excluded;
|
||||
}
|
||||
|
||||
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) {
|
||||
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;
|
||||
return;
|
||||
}
|
||||
|
||||
tld->resolution = TldResolutionOk;
|
||||
|
||||
ConstExprValue *const_val = &expr->instruction->static_value;
|
||||
ConstExprValue *const_val = &use_target_value->static_value;
|
||||
assert(const_val->special != ConstValSpecialRuntime);
|
||||
|
||||
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);
|
||||
if (get_as_top_level_decl(node)->resolution != TldResolutionUnresolved) {
|
||||
return;
|
||||
|
@ -2519,7 +2515,7 @@ static void resolve_use_decl(CodeGen *g, AstNode *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);
|
||||
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) {
|
||||
switch (node->type) {
|
||||
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 result = 0;
|
||||
result += hash_ptr(id->decl_node);
|
||||
for (size_t i = 0; i < id->generic_param_count; i += 1) {
|
||||
GenericParamValue *generic_param = &id->generic_params[i];
|
||||
if (generic_param->node) {
|
||||
ConstExprValue *const_val = &get_resolved_expr(generic_param->node)->instruction->static_value;
|
||||
assert(const_val->special != ConstValSpecialRuntime);
|
||||
result += hash_const_val(generic_param->type, const_val);
|
||||
}
|
||||
result += hash_ptr(generic_param->type);
|
||||
}
|
||||
return result;
|
||||
zig_panic("TODO generic_fn_type_id_hash");
|
||||
//uint32_t result = 0;
|
||||
//result += hash_ptr(id->decl_node);
|
||||
//for (size_t i = 0; i < id->generic_param_count; i += 1) {
|
||||
// GenericParamValue *generic_param = &id->generic_params[i];
|
||||
// if (generic_param->node) {
|
||||
// ConstExprValue *const_val = &get_resolved_expr(generic_param->node)->instruction->static_value;
|
||||
// assert(const_val->special != ConstValSpecialRuntime);
|
||||
// result += hash_const_val(generic_param->type, const_val);
|
||||
// }
|
||||
// result += hash_ptr(generic_param->type);
|
||||
//}
|
||||
//return result;
|
||||
}
|
||||
|
||||
bool generic_fn_type_id_eql(GenericFnTypeId *a, GenericFnTypeId *b) {
|
||||
if (a->decl_node != b->decl_node) return false;
|
||||
assert(a->generic_param_count == b->generic_param_count);
|
||||
for (size_t i = 0; i < a->generic_param_count; i += 1) {
|
||||
GenericParamValue *a_val = &a->generic_params[i];
|
||||
GenericParamValue *b_val = &b->generic_params[i];
|
||||
if (a_val->type != b_val->type) return false;
|
||||
if (a_val->node && b_val->node) {
|
||||
ConstExprValue *a_const_val = &get_resolved_expr(a_val->node)->instruction->static_value;
|
||||
ConstExprValue *b_const_val = &get_resolved_expr(b_val->node)->instruction->static_value;
|
||||
assert(a_const_val->special != ConstValSpecialRuntime);
|
||||
assert(b_const_val->special != ConstValSpecialRuntime);
|
||||
if (!const_values_equal(a_const_val, b_const_val, a_val->type)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
assert(!a_val->node && !b_val->node);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
zig_panic("TODO generic_fn_type_id_eql");
|
||||
//if (a->decl_node != b->decl_node) return false;
|
||||
//assert(a->generic_param_count == b->generic_param_count);
|
||||
//for (size_t i = 0; i < a->generic_param_count; i += 1) {
|
||||
// GenericParamValue *a_val = &a->generic_params[i];
|
||||
// GenericParamValue *b_val = &b->generic_params[i];
|
||||
// if (a_val->type != b_val->type) return false;
|
||||
// if (a_val->node && b_val->node) {
|
||||
// ConstExprValue *a_const_val = &get_resolved_expr(a_val->node)->instruction->static_value;
|
||||
// ConstExprValue *b_const_val = &get_resolved_expr(b_val->node)->instruction->static_value;
|
||||
// assert(a_const_val->special != ConstValSpecialRuntime);
|
||||
// assert(b_const_val->special != ConstValSpecialRuntime);
|
||||
// if (!const_values_equal(a_const_val, b_const_val, a_val->type)) {
|
||||
// return false;
|
||||
// }
|
||||
// } else {
|
||||
// assert(!a_val->node && !b_val->node);
|
||||
// }
|
||||
//}
|
||||
//return true;
|
||||
}
|
||||
|
||||
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);
|
||||
return LLVMABISizeOfType(g->target_data_ref, first_type_in_mem->type_ref);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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 *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const);
|
||||
BlockContext *new_block_context(AstNode *node, BlockContext *parent);
|
||||
Expr *get_resolved_expr(AstNode *node);
|
||||
bool is_node_void_expr(AstNode *node);
|
||||
uint64_t type_size(CodeGen *g, TypeTableEntry *type_entry);
|
||||
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);
|
||||
TypeEnumField *find_enum_type_field(TypeTableEntry *enum_type, Buf *name);
|
||||
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
|
||||
|
|
|
@ -528,15 +528,13 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
|
|||
break;
|
||||
}
|
||||
case NodeTypeFnCallExpr:
|
||||
{
|
||||
if (node->data.fn_call_expr.is_builtin) {
|
||||
fprintf(ar->f, "@");
|
||||
} else {
|
||||
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, ")");
|
||||
}
|
||||
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);
|
||||
|
@ -547,6 +545,7 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
|
|||
}
|
||||
fprintf(ar->f, ")");
|
||||
break;
|
||||
}
|
||||
case NodeTypeArrayAccessExpr:
|
||||
render_node_ungrouped(ar, node->data.array_access_expr.array_ref_expr);
|
||||
fprintf(ar->f, "[");
|
||||
|
|
|
@ -65,8 +65,6 @@ CodeGen *codegen_create(Buf *root_source_dir, const ZigTarget *target) {
|
|||
g->is_test_build = false;
|
||||
g->want_h_file = true;
|
||||
|
||||
g->len_buf = buf_create_from_str("len");
|
||||
|
||||
// the error.Ok value
|
||||
g->error_decls.append(nullptr);
|
||||
|
||||
|
@ -1682,6 +1680,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
|
|||
case IrInstructionIdSizeOf:
|
||||
case IrInstructionIdSwitchTarget:
|
||||
case IrInstructionIdStaticEval:
|
||||
case IrInstructionIdImport:
|
||||
zig_unreachable();
|
||||
case IrInstructionIdReturn:
|
||||
return ir_render_return(g, executable, (IrInstructionReturn *)instruction);
|
||||
|
@ -1728,8 +1727,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
|
|||
case IrInstructionIdSwitchVar:
|
||||
case IrInstructionIdContainerInitList:
|
||||
case IrInstructionIdContainerInitFields:
|
||||
case IrInstructionIdReadField:
|
||||
case IrInstructionIdEnumTag:
|
||||
case IrInstructionIdArrayLen:
|
||||
zig_panic("TODO render more IR instructions to LLVM");
|
||||
}
|
||||
zig_unreachable();
|
||||
|
@ -2114,7 +2113,7 @@ static void do_code_gen(CodeGen *g) {
|
|||
|
||||
if (var->type->id == TypeTableEntryIdNumLitFloat) {
|
||||
// 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);
|
||||
TypeTableEntry *var_type = g->builtin_types.entry_f64;
|
||||
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) {
|
||||
// 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);
|
||||
TypeTableEntry *var_type = const_val->data.x_bignum.is_negative ?
|
||||
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);
|
||||
} else {
|
||||
AstNode *expr_node = var->decl_node->data.variable_declaration.expr;
|
||||
IrInstruction *instruction = get_resolved_expr(expr_node)->instruction;
|
||||
IrInstruction *instruction = var->decl_node->data.variable_declaration.top_level_decl.value;
|
||||
render_const_val(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;
|
||||
|
|
1178
src/ir.cpp
1178
src/ir.cpp
File diff suppressed because it is too large
Load Diff
|
@ -115,6 +115,12 @@ static void ir_print_const_value(IrPrint *irp, TypeTableEntry *type_entry, Const
|
|||
}
|
||||
break;
|
||||
}
|
||||
case TypeTableEntryIdNamespace:
|
||||
{
|
||||
ImportTableEntry *import = const_val->data.x_import;
|
||||
fprintf(irp->f, "(namespace: %s)", buf_ptr(import->path));
|
||||
break;
|
||||
}
|
||||
case TypeTableEntryIdVar:
|
||||
case TypeTableEntryIdFloat:
|
||||
case TypeTableEntryIdStruct:
|
||||
|
@ -124,7 +130,6 @@ static void ir_print_const_value(IrPrint *irp, TypeTableEntry *type_entry, Const
|
|||
case TypeTableEntryIdEnum:
|
||||
case TypeTableEntryIdUnion:
|
||||
case TypeTableEntryIdTypeDecl:
|
||||
case TypeTableEntryIdNamespace:
|
||||
case TypeTableEntryIdGenericFn:
|
||||
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, ")");
|
||||
}
|
||||
|
||||
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) {
|
||||
fprintf(irp->f, "@StructFieldPtr(&");
|
||||
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, ")");
|
||||
}
|
||||
|
||||
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) {
|
||||
ir_print_prefix(irp, instruction);
|
||||
switch (instruction->id) {
|
||||
|
@ -643,9 +654,6 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
|
|||
case IrInstructionIdFieldPtr:
|
||||
ir_print_field_ptr(irp, (IrInstructionFieldPtr *)instruction);
|
||||
break;
|
||||
case IrInstructionIdReadField:
|
||||
ir_print_read_field(irp, (IrInstructionReadField *)instruction);
|
||||
break;
|
||||
case IrInstructionIdStructFieldPtr:
|
||||
ir_print_struct_field_ptr(irp, (IrInstructionStructFieldPtr *)instruction);
|
||||
break;
|
||||
|
@ -700,6 +708,12 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
|
|||
case IrInstructionIdStaticEval:
|
||||
ir_print_static_eval(irp, (IrInstructionStaticEval *)instruction);
|
||||
break;
|
||||
case IrInstructionIdImport:
|
||||
ir_print_import(irp, (IrInstructionImport *)instruction);
|
||||
break;
|
||||
case IrInstructionIdArrayLen:
|
||||
ir_print_array_len(irp, (IrInstructionArrayLen *)instruction);
|
||||
break;
|
||||
}
|
||||
fprintf(irp->f, "\n");
|
||||
}
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
pub fn foo() -> i32 { 1234 }
|
|
@ -1,3 +1,5 @@
|
|||
const case_namespace_fn_call = @import("cases/namespace_fn_call.zig");
|
||||
|
||||
pub const SYS_write = 1;
|
||||
pub const SYS_exit = 60;
|
||||
pub const stdout_fileno = 1;
|
||||
|
@ -61,6 +63,10 @@ fn testInlineSwitch() {
|
|||
assert(result + 1 == 14);
|
||||
}
|
||||
|
||||
fn testNamespaceFnCall() {
|
||||
assert(case_namespace_fn_call.foo() == 1234);
|
||||
}
|
||||
|
||||
fn assert(ok: bool) {
|
||||
if (!ok)
|
||||
@unreachable();
|
||||
|
@ -73,6 +79,7 @@ fn runAllTests() {
|
|||
switchWithNumbers();
|
||||
switchWithAllRanges();
|
||||
testInlineSwitch();
|
||||
testNamespaceFnCall();
|
||||
}
|
||||
|
||||
export nakedcc fn _start() -> unreachable {
|
||||
|
|
Loading…
Reference in New Issue