Merge pull request #4290 from ziglang/split-ir-structs

split IrInstruction into IrInst, IrInstSrc, IrInstGen
This commit is contained in:
Andrew Kelley 2020-01-25 23:24:41 -05:00 committed by GitHub
commit 4e9b1f5479
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 11271 additions and 9253 deletions

File diff suppressed because it is too large Load Diff

View File

@ -199,7 +199,7 @@ ScopeLoop *create_loop_scope(CodeGen *g, AstNode *node, Scope *parent) {
return scope;
}
Scope *create_runtime_scope(CodeGen *g, AstNode *node, Scope *parent, IrInstruction *is_comptime) {
Scope *create_runtime_scope(CodeGen *g, AstNode *node, Scope *parent, IrInstSrc *is_comptime) {
ScopeRuntime *scope = allocate<ScopeRuntime>(1);
scope->is_comptime = is_comptime;
init_scope(g, &scope->base, ScopeIdRuntime, node, parent);
@ -3350,7 +3350,7 @@ static void get_fully_qualified_decl_name(CodeGen *g, Buf *buf, Tld *tld, bool i
ZigFn *create_fn_raw(CodeGen *g, FnInline inline_value) {
ZigFn *fn_entry = allocate<ZigFn>(1, "ZigFn");
fn_entry->ir_executable = allocate<IrExecutable>(1, "IrExecutablePass1");
fn_entry->ir_executable = allocate<IrExecutableSrc>(1, "IrExecutableSrc");
fn_entry->prealloc_backward_branch_quota = default_backward_branch_quota;
@ -4097,7 +4097,7 @@ static void preview_use_decl(CodeGen *g, TldUsingNamespace *using_namespace, Sco
if (type_is_invalid(result->type)) {
dest_decls_scope->any_imports_failed = true;
using_namespace->base.resolution = TldResolutionInvalid;
using_namespace->using_namespace_value = g->invalid_instruction->value;
using_namespace->using_namespace_value = g->invalid_inst_gen->value;
return;
}
@ -4106,7 +4106,7 @@ static void preview_use_decl(CodeGen *g, TldUsingNamespace *using_namespace, Sco
buf_sprintf("expected struct, enum, or union; found '%s'", buf_ptr(&result->data.x_type->name)));
dest_decls_scope->any_imports_failed = true;
using_namespace->base.resolution = TldResolutionInvalid;
using_namespace->using_namespace_value = g->invalid_instruction->value;
using_namespace->using_namespace_value = g->invalid_inst_gen->value;
return;
}
}
@ -4667,12 +4667,12 @@ static void analyze_fn_async(CodeGen *g, ZigFn *fn, bool resolve_frame) {
}
for (size_t i = 0; i < fn->call_list.length; i += 1) {
IrInstructionCallGen *call = fn->call_list.at(i);
IrInstGenCall *call = fn->call_list.at(i);
if (call->fn_entry == nullptr) {
// TODO function pointer call here, could be anything
continue;
}
switch (analyze_callee_async(g, fn, call->fn_entry, call->base.source_node, must_not_be_async,
switch (analyze_callee_async(g, fn, call->fn_entry, call->base.base.source_node, must_not_be_async,
call->modifier))
{
case ErrorSemanticAnalyzeFail:
@ -4690,10 +4690,10 @@ static void analyze_fn_async(CodeGen *g, ZigFn *fn, bool resolve_frame) {
}
}
for (size_t i = 0; i < fn->await_list.length; i += 1) {
IrInstructionAwaitGen *await = fn->await_list.at(i);
IrInstGenAwait *await = fn->await_list.at(i);
// TODO If this is a noasync await, it doesn't count
// https://github.com/ziglang/zig/issues/3157
switch (analyze_callee_async(g, fn, await->target_fn, await->base.source_node, must_not_be_async,
switch (analyze_callee_async(g, fn, await->target_fn, await->base.base.source_node, must_not_be_async,
CallModifierNone))
{
case ErrorSemanticAnalyzeFail:
@ -4784,7 +4784,7 @@ static void analyze_fn_ir(CodeGen *g, ZigFn *fn, AstNode *return_type_node) {
if (g->verbose_ir) {
fprintf(stderr, "fn %s() { // (analyzed)\n", buf_ptr(&fn->symbol_name));
ir_print(g, stderr, &fn->analyzed_executable, 4, IrPassGen);
ir_print_gen(g, stderr, &fn->analyzed_executable, 4);
fprintf(stderr, "}\n");
}
fn->anal_state = FnAnalStateComplete;
@ -4827,7 +4827,7 @@ static void analyze_fn_body(CodeGen *g, ZigFn *fn_table_entry) {
fprintf(stderr, "\n");
ast_render(stderr, fn_table_entry->body_node, 4);
fprintf(stderr, "\nfn %s() { // (IR)\n", buf_ptr(&fn_table_entry->symbol_name));
ir_print(g, stderr, fn_table_entry->ir_executable, 4, IrPassSrc);
ir_print_src(g, stderr, fn_table_entry->ir_executable, 4);
fprintf(stderr, "}\n");
}
@ -6191,13 +6191,13 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
ZigType *fn_type = get_async_fn_type(g, fn->type_entry);
if (fn->analyzed_executable.need_err_code_spill) {
IrInstructionAllocaGen *alloca_gen = allocate<IrInstructionAllocaGen>(1);
alloca_gen->base.id = IrInstructionIdAllocaGen;
alloca_gen->base.source_node = fn->proto_node;
alloca_gen->base.scope = fn->child_scope;
IrInstGenAlloca *alloca_gen = allocate<IrInstGenAlloca>(1);
alloca_gen->base.id = IrInstGenIdAlloca;
alloca_gen->base.base.source_node = fn->proto_node;
alloca_gen->base.base.scope = fn->child_scope;
alloca_gen->base.value = allocate<ZigValue>(1, "ZigValue");
alloca_gen->base.value->type = get_pointer_to_type(g, g->builtin_types.entry_global_error_set, false);
alloca_gen->base.ref_count = 1;
alloca_gen->base.base.ref_count = 1;
alloca_gen->name_hint = "";
fn->alloca_gen_list.append(alloca_gen);
fn->err_code_spill = &alloca_gen->base;
@ -6205,18 +6205,18 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
ZigType *largest_call_frame_type = nullptr;
// Later we'll change this to be largest_call_frame_type instead of void.
IrInstruction *all_calls_alloca = ir_create_alloca(g, &fn->fndef_scope->base, fn->body_node,
IrInstGen *all_calls_alloca = ir_create_alloca(g, &fn->fndef_scope->base, fn->body_node,
fn, g->builtin_types.entry_void, "@async_call_frame");
for (size_t i = 0; i < fn->call_list.length; i += 1) {
IrInstructionCallGen *call = fn->call_list.at(i);
IrInstGenCall *call = fn->call_list.at(i);
if (call->new_stack != nullptr) {
// don't need to allocate a frame for this
continue;
}
ZigFn *callee = call->fn_entry;
if (callee == nullptr) {
add_node_error(g, call->base.source_node,
add_node_error(g, call->base.base.source_node,
buf_sprintf("function is not comptime-known; @asyncCall required"));
return ErrorSemanticAnalyzeFail;
}
@ -6226,14 +6226,14 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
if (callee->anal_state == FnAnalStateProbing) {
ErrorMsg *msg = add_node_error(g, fn->proto_node,
buf_sprintf("unable to determine async function frame of '%s'", buf_ptr(&fn->symbol_name)));
g->trace_err = add_error_note(g, msg, call->base.source_node,
g->trace_err = add_error_note(g, msg, call->base.base.source_node,
buf_sprintf("analysis of function '%s' depends on the frame", buf_ptr(&callee->symbol_name)));
return ErrorSemanticAnalyzeFail;
}
ZigType *callee_frame_type = get_fn_frame_type(g, callee);
frame_type->data.frame.resolve_loop_type = callee_frame_type;
frame_type->data.frame.resolve_loop_src_node = call->base.source_node;
frame_type->data.frame.resolve_loop_src_node = call->base.base.source_node;
analyze_fn_body(g, callee);
if (callee->anal_state == FnAnalStateInvalid) {
@ -6249,7 +6249,7 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
if (!fn_is_async(callee))
continue;
mark_suspension_point(call->base.scope);
mark_suspension_point(call->base.base.scope);
if ((err = type_resolve(g, callee_frame_type, ResolveStatusSizeKnown))) {
return err;
@ -6271,7 +6271,7 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
// For example: foo() + await z
// The funtion call result of foo() must be spilled.
for (size_t i = 0; i < fn->await_list.length; i += 1) {
IrInstructionAwaitGen *await = fn->await_list.at(i);
IrInstGenAwait *await = fn->await_list.at(i);
// TODO If this is a noasync await, it doesn't suspend
// https://github.com/ziglang/zig/issues/3157
if (await->base.value->special != ConstValSpecialRuntime) {
@ -6293,52 +6293,51 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
}
// This await is a suspend point, but it might not need a spill.
// We do need to mark the ExprScope as having a suspend point in it.
mark_suspension_point(await->base.scope);
mark_suspension_point(await->base.base.scope);
if (await->result_loc != nullptr) {
// If there's a result location, that is the spill
continue;
}
if (await->base.ref_count == 0)
if (await->base.base.ref_count == 0)
continue;
if (!type_has_bits(await->base.value->type))
continue;
await->result_loc = ir_create_alloca(g, await->base.scope, await->base.source_node, fn,
await->result_loc = ir_create_alloca(g, await->base.base.scope, await->base.base.source_node, fn,
await->base.value->type, "");
}
for (size_t block_i = 0; block_i < fn->analyzed_executable.basic_block_list.length; block_i += 1) {
IrBasicBlock *block = fn->analyzed_executable.basic_block_list.at(block_i);
IrBasicBlockGen *block = fn->analyzed_executable.basic_block_list.at(block_i);
for (size_t instr_i = 0; instr_i < block->instruction_list.length; instr_i += 1) {
IrInstruction *instruction = block->instruction_list.at(instr_i);
if (instruction->id == IrInstructionIdSuspendFinish) {
mark_suspension_point(instruction->scope);
IrInstGen *instruction = block->instruction_list.at(instr_i);
if (instruction->id == IrInstGenIdSuspendFinish) {
mark_suspension_point(instruction->base.scope);
}
}
}
// Now that we've marked all the expr scopes that have to spill, we go over the instructions
// and spill the relevant ones.
for (size_t block_i = 0; block_i < fn->analyzed_executable.basic_block_list.length; block_i += 1) {
IrBasicBlock *block = fn->analyzed_executable.basic_block_list.at(block_i);
IrBasicBlockGen *block = fn->analyzed_executable.basic_block_list.at(block_i);
for (size_t instr_i = 0; instr_i < block->instruction_list.length; instr_i += 1) {
IrInstruction *instruction = block->instruction_list.at(instr_i);
if (instruction->id == IrInstructionIdAwaitGen ||
instruction->id == IrInstructionIdVarPtr ||
instruction->id == IrInstructionIdDeclRef ||
instruction->id == IrInstructionIdAllocaGen)
IrInstGen *instruction = block->instruction_list.at(instr_i);
if (instruction->id == IrInstGenIdAwait ||
instruction->id == IrInstGenIdVarPtr ||
instruction->id == IrInstGenIdAlloca)
{
// This instruction does its own spilling specially, or otherwise doesn't need it.
continue;
}
if (instruction->value->special != ConstValSpecialRuntime)
continue;
if (instruction->ref_count == 0)
if (instruction->base.ref_count == 0)
continue;
if ((err = type_resolve(g, instruction->value->type, ResolveStatusZeroBitsKnown)))
return ErrorSemanticAnalyzeFail;
if (!type_has_bits(instruction->value->type))
continue;
if (scope_needs_spill(instruction->scope)) {
instruction->spill = ir_create_alloca(g, instruction->scope, instruction->source_node,
if (scope_needs_spill(instruction->base.scope)) {
instruction->spill = ir_create_alloca(g, instruction->base.scope, instruction->base.source_node,
fn, instruction->value->type, "");
}
}
@ -6389,14 +6388,14 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
}
for (size_t alloca_i = 0; alloca_i < fn->alloca_gen_list.length; alloca_i += 1) {
IrInstructionAllocaGen *instruction = fn->alloca_gen_list.at(alloca_i);
IrInstGenAlloca *instruction = fn->alloca_gen_list.at(alloca_i);
instruction->field_index = SIZE_MAX;
ZigType *ptr_type = instruction->base.value->type;
assert(ptr_type->id == ZigTypeIdPointer);
ZigType *child_type = ptr_type->data.pointer.child_type;
if (!type_has_bits(child_type))
continue;
if (instruction->base.ref_count == 0)
if (instruction->base.base.ref_count == 0)
continue;
if (instruction->base.value->special != ConstValSpecialRuntime) {
if (const_ptr_pointee(nullptr, g, instruction->base.value, nullptr)->special !=
@ -6407,7 +6406,7 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
}
frame_type->data.frame.resolve_loop_type = child_type;
frame_type->data.frame.resolve_loop_src_node = instruction->base.source_node;
frame_type->data.frame.resolve_loop_src_node = instruction->base.base.source_node;
if ((err = type_resolve(g, child_type, ResolveStatusSizeKnown))) {
return err;
}
@ -6421,7 +6420,7 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
instruction->field_index = fields.length;
src_assert(child_type->id != ZigTypeIdPointer || child_type->data.pointer.inferred_struct_field == nullptr,
instruction->base.source_node);
instruction->base.base.source_node);
fields.append({name, child_type, instruction->align});
}
@ -6554,8 +6553,10 @@ bool ir_get_var_is_comptime(ZigVar *var) {
// As an optimization, is_comptime values which are constant are allowed
// to be omitted from analysis. In this case, there is no child instruction
// and we simply look at the unanalyzed const parent instruction.
assert(var->is_comptime->value->type->id == ZigTypeIdBool);
var->is_comptime_memoized_value = var->is_comptime->value->data.x_bool;
assert(var->is_comptime->id == IrInstSrcIdConst);
IrInstSrcConst *const_inst = reinterpret_cast<IrInstSrcConst *>(var->is_comptime);
assert(const_inst->value->type->id == ZigTypeIdBool);
var->is_comptime_memoized_value = const_inst->value->data.x_bool;
var->is_comptime = nullptr;
return var->is_comptime_memoized_value;
}
@ -9193,21 +9194,6 @@ void src_assert(bool ok, AstNode *source_node) {
stage2_panic(msg, strlen(msg));
}
IrInstruction *ir_create_alloca(CodeGen *g, Scope *scope, AstNode *source_node, ZigFn *fn,
ZigType *var_type, const char *name_hint)
{
IrInstructionAllocaGen *alloca_gen = allocate<IrInstructionAllocaGen>(1);
alloca_gen->base.id = IrInstructionIdAllocaGen;
alloca_gen->base.source_node = source_node;
alloca_gen->base.scope = scope;
alloca_gen->base.value = allocate<ZigValue>(1, "ZigValue");
alloca_gen->base.value->type = get_pointer_to_type(g, var_type, false);
alloca_gen->base.ref_count = 1;
alloca_gen->name_hint = name_hint;
fn->alloca_gen_list.append(alloca_gen);
return &alloca_gen->base;
}
Error analyze_import(CodeGen *g, ZigType *source_import, Buf *import_target_str,
ZigType **out_import, Buf **out_import_target_path, Buf *out_full_path)
{
@ -9268,8 +9254,17 @@ Error analyze_import(CodeGen *g, ZigType *source_import, Buf *import_target_str,
}
void IrExecutable::src() {
IrExecutable *it;
void IrExecutableSrc::src() {
if (this->source_node != nullptr) {
this->source_node->src();
}
if (this->parent_exec != nullptr) {
this->parent_exec->src();
}
}
void IrExecutableGen::src() {
IrExecutableGen *it;
for (it = this; it != nullptr && it->source_node != nullptr; it = it->parent_exec) {
it->source_node->src();
}
@ -9357,3 +9352,41 @@ bool type_is_numeric(ZigType *ty) {
}
zig_unreachable();
}
// float ops that take a single argument
//TODO Powi, Pow, minnum, maxnum, maximum, minimum, copysign, lround, llround, lrint, llrint
const char *float_op_to_name(BuiltinFnId op) {
switch (op) {
case BuiltinFnIdSqrt:
return "sqrt";
case BuiltinFnIdSin:
return "sin";
case BuiltinFnIdCos:
return "cos";
case BuiltinFnIdExp:
return "exp";
case BuiltinFnIdExp2:
return "exp2";
case BuiltinFnIdLog:
return "log";
case BuiltinFnIdLog10:
return "log10";
case BuiltinFnIdLog2:
return "log2";
case BuiltinFnIdFabs:
return "fabs";
case BuiltinFnIdFloor:
return "floor";
case BuiltinFnIdCeil:
return "ceil";
case BuiltinFnIdTrunc:
return "trunc";
case BuiltinFnIdNearbyInt:
return "nearbyint";
case BuiltinFnIdRound:
return "round";
default:
zig_unreachable();
}
}

View File

@ -120,7 +120,7 @@ ScopeLoop *create_loop_scope(CodeGen *g, AstNode *node, Scope *parent);
ScopeSuspend *create_suspend_scope(CodeGen *g, AstNode *node, Scope *parent);
ScopeFnDef *create_fndef_scope(CodeGen *g, AstNode *node, Scope *parent, ZigFn *fn_entry);
Scope *create_comptime_scope(CodeGen *g, AstNode *node, Scope *parent);
Scope *create_runtime_scope(CodeGen *g, AstNode *node, Scope *parent, IrInstruction *is_comptime);
Scope *create_runtime_scope(CodeGen *g, AstNode *node, Scope *parent, IrInstSrc *is_comptime);
Scope *create_typeof_scope(CodeGen *g, AstNode *node, Scope *parent);
ScopeExpr *create_expr_scope(CodeGen *g, AstNode *node, Scope *parent);
@ -271,8 +271,6 @@ ZigType *resolve_struct_field_type(CodeGen *g, TypeStructField *struct_field);
void add_async_error_notes(CodeGen *g, ErrorMsg *msg, ZigFn *fn);
IrInstruction *ir_create_alloca(CodeGen *g, Scope *scope, AstNode *source_node, ZigFn *fn,
ZigType *var_type, const char *name_hint);
Error analyze_import(CodeGen *codegen, ZigType *source_import, Buf *import_target_str,
ZigType **out_import, Buf **out_import_target_path, Buf *out_full_path);
ZigValue *get_the_one_possible_value(CodeGen *g, ZigType *type_entry);
@ -281,4 +279,5 @@ void copy_const_val(ZigValue *dest, ZigValue *src);
bool type_has_optional_repr(ZigType *ty);
bool is_opt_err_set(ZigType *ty);
bool type_is_numeric(ZigType *ty);
const char *float_op_to_name(BuiltinFnId op);
#endif

File diff suppressed because it is too large Load Diff

13735
src/ir.cpp

File diff suppressed because it is too large Load Diff

View File

@ -10,33 +10,33 @@
#include "all_types.hpp"
enum IrPass {
IrPassSrc,
IrPassGen,
};
bool ir_gen(CodeGen *g, AstNode *node, Scope *scope, IrExecutable *ir_executable);
bool ir_gen(CodeGen *g, AstNode *node, Scope *scope, IrExecutableSrc *ir_executable);
bool ir_gen_fn(CodeGen *g, ZigFn *fn_entry);
IrInstGen *ir_create_alloca(CodeGen *g, Scope *scope, AstNode *source_node, ZigFn *fn,
ZigType *var_type, const char *name_hint);
ZigValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,
ZigType *expected_type, size_t *backward_branch_count, size_t *backward_branch_quota,
ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name,
IrExecutable *parent_exec, AstNode *expected_type_source_node, UndefAllowed undef);
IrExecutableGen *parent_exec, AstNode *expected_type_source_node, UndefAllowed undef);
Error ir_resolve_lazy(CodeGen *codegen, AstNode *source_node, ZigValue *val);
ZigType *ir_analyze(CodeGen *g, IrExecutable *old_executable, IrExecutable *new_executable,
ZigType *ir_analyze(CodeGen *g, IrExecutableSrc *old_executable, IrExecutableGen *new_executable,
ZigType *expected_type, AstNode *expected_type_source_node);
bool ir_has_side_effects(IrInstruction *instruction);
bool ir_inst_gen_has_side_effects(IrInstGen *inst);
bool ir_inst_src_has_side_effects(IrInstSrc *inst);
struct IrAnalyze;
ZigValue *const_ptr_pointee(IrAnalyze *ira, CodeGen *codegen, ZigValue *const_val,
AstNode *source_node);
const char *float_op_to_name(BuiltinFnId op);
// for debugging purposes
void dbg_ir_break(const char *src_file, uint32_t line);
void dbg_ir_clear(void);
void destroy_instruction_gen(IrInstGen *inst);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -12,11 +12,14 @@
#include <stdio.h>
void ir_print(CodeGen *codegen, FILE *f, IrExecutable *executable, int indent_size, IrPass pass);
void ir_print_instruction(CodeGen *codegen, FILE *f, IrInstruction *instruction, int indent_size, IrPass pass);
void ir_print_const_expr(CodeGen *codegen, FILE *f, ZigValue *value, int indent_size, IrPass pass);
void ir_print_basic_block(CodeGen *codegen, FILE *f, IrBasicBlock *bb, int indent_size, IrPass pass);
void ir_print_src(CodeGen *codegen, FILE *f, IrExecutableSrc *executable, int indent_size);
void ir_print_gen(CodeGen *codegen, FILE *f, IrExecutableGen *executable, int indent_size);
void ir_print_inst_src(CodeGen *codegen, FILE *f, IrInstSrc *inst, int indent_size);
void ir_print_inst_gen(CodeGen *codegen, FILE *f, IrInstGen *inst, int indent_size);
void ir_print_basic_block_src(CodeGen *codegen, FILE *f, IrBasicBlockSrc *bb, int indent_size);
void ir_print_basic_block_gen(CodeGen *codegen, FILE *f, IrBasicBlockGen *bb, int indent_size);
const char* ir_instruction_type_str(IrInstructionId id);
const char* ir_inst_src_type_str(IrInstSrcId id);
const char* ir_inst_gen_type_str(IrInstGenId id);
#endif

View File

@ -147,7 +147,7 @@ static void ast_invalid_token_error(ParseContext *pc, Token *token) {
}
static AstNode *ast_create_node_no_line_info(ParseContext *pc, NodeType type) {
AstNode *node = allocate<AstNode>(1);
AstNode *node = allocate<AstNode>(1, "AstNode");
node->type = type;
node->owner = pc->owner;
return node;