empty function compiles successfully with IR

This commit is contained in:
Andrew Kelley
2016-09-30 20:12:00 -04:00
parent 4e2fa2d15b
commit 633781e31d
10 changed files with 612 additions and 250 deletions

View File

@@ -5,18 +5,18 @@
* See http://opensource.org/licenses/MIT
*/
#include "codegen.hpp"
#include "hash_map.hpp"
#include "zig_llvm.hpp"
#include "os.hpp"
#include "config.h"
#include "error.hpp"
#include "analyze.hpp"
#include "errmsg.hpp"
#include "parseh.hpp"
#include "ast_render.hpp"
#include "target.hpp"
#include "codegen.hpp"
#include "config.h"
#include "errmsg.hpp"
#include "error.hpp"
#include "hash_map.hpp"
#include "link.hpp"
#include "os.hpp"
#include "parseh.hpp"
#include "target.hpp"
#include "zig_llvm.hpp"
#include <stdio.h>
#include <errno.h>
@@ -65,6 +65,8 @@ CodeGen *codegen_create(Buf *root_source_dir, const ZigTarget *target) {
g->is_test_build = false;
g->want_h_file = true;
g->invalid_instruction = allocate<IrInstruction>(1);
// the error.Ok value
g->error_decls.append(nullptr);
@@ -235,6 +237,7 @@ static LLVMValueRef gen_assign_raw(CodeGen *g, AstNode *source_node, BinOpType b
static LLVMValueRef gen_unwrap_maybe(CodeGen *g, AstNode *node, LLVMValueRef maybe_struct_ref);
static LLVMValueRef gen_div(CodeGen *g, AstNode *source_node, LLVMValueRef val1, LLVMValueRef val2,
TypeTableEntry *type_entry, bool exact);
static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val);
static TypeTableEntry *get_type_for_type_node(AstNode *node) {
Expr *expr = get_resolved_expr(node);
@@ -249,6 +252,10 @@ static void set_debug_source_node(CodeGen *g, AstNode *node) {
ZigLLVMSetCurrentDebugLocation(g->builder, node->line + 1, node->column + 1, node->block_context->di_scope);
}
static void ir_set_debug(CodeGen *g, IrInstruction *instruction) {
set_debug_source_node(g, instruction->source_node);
}
static void clear_debug_source_node(CodeGen *g) {
ZigLLVMClearCurrentDebugLocation(g->builder);
}
@@ -2792,6 +2799,47 @@ static LLVMValueRef gen_if_var_expr(CodeGen *g, AstNode *node) {
return nullptr;
}
static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrInstructionReturn *return_instruction) {
ir_set_debug(g, &return_instruction->base);
LLVMBuildRet(g->builder, return_instruction->value->llvm_value);
return nullptr;
}
static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, IrInstruction *instruction) {
switch (instruction->id) {
case IrInstructionIdInvalid:
zig_unreachable();
case IrInstructionIdConst:
return gen_const_val(g, instruction->type_entry, &instruction->static_value);
case IrInstructionIdReturn:
return ir_render_return(g, executable, (IrInstructionReturn *)instruction);
case IrInstructionIdCondBr:
case IrInstructionIdSwitchBr:
case IrInstructionIdPhi:
case IrInstructionIdBinOp:
case IrInstructionIdLoadVar:
case IrInstructionIdStoreVar:
case IrInstructionIdCall:
case IrInstructionIdBuiltinCall:
zig_panic("TODO render more IR instructions to LLVM");
}
zig_unreachable();
}
static void ir_render(CodeGen *g, FnTableEntry *fn_entry) {
assert(fn_entry);
IrExecutable *executable = &fn_entry->ir_executable;
assert(executable->basic_block_count > 0);
for (size_t i = 0; i < executable->basic_block_count; i += 1) {
IrBasicBlock *current_block = executable->basic_block_list[i];
for (IrInstruction *instruction = current_block->first; instruction != nullptr;
instruction = instruction->next)
{
instruction->llvm_value = ir_render_instruction(g, executable, instruction);
}
}
}
static LLVMValueRef gen_block(CodeGen *g, AstNode *block_node, TypeTableEntry *implicit_return_type) {
assert(block_node->type == NodeTypeBlock);
@@ -3836,6 +3884,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE
return LLVMConstStruct(fields, 2, false);
}
}
case TypeTableEntryIdVoid:
return nullptr;
case TypeTableEntryIdInvalid:
case TypeTableEntryIdMetaType:
case TypeTableEntryIdUnreachable:
@@ -3843,7 +3893,6 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE
case TypeTableEntryIdNumLitInt:
case TypeTableEntryIdUndefLit:
case TypeTableEntryIdNullLit:
case TypeTableEntryIdVoid:
case TypeTableEntryIdNamespace:
case TypeTableEntryIdBlock:
case TypeTableEntryIdGenericFn:
@@ -4199,7 +4248,6 @@ static void do_code_gen(CodeGen *g) {
}
ImportTableEntry *import = fn_table_entry->import_entry;
AstNode *fn_def_node = fn_table_entry->fn_def_node;
LLVMValueRef fn = fn_table_entry->fn_value;
g->cur_fn = fn_table_entry;
if (handle_is_ptr(fn_table_entry->type_entry->data.fn.fn_type_id.return_type)) {
@@ -4307,9 +4355,7 @@ static void do_code_gen(CodeGen *g) {
gen_var_debug_decl(g, variable);
}
TypeTableEntry *implicit_return_type = fn_def_node->data.fn_def.implicit_return_type;
gen_block(g, fn_def_node->data.fn_def.body, implicit_return_type);
ir_render(g, fn_table_entry);
}
assert(!g->errors.length);
@@ -4967,7 +5013,6 @@ static void init(CodeGen *g, Buf *source_path) {
define_builtin_types(g);
define_builtin_fns(g);
}
void codegen_parseh(CodeGen *g, Buf *src_dirname, Buf *src_basename, Buf *source_code) {
@@ -5078,6 +5123,7 @@ void codegen_add_root_code(CodeGen *g, Buf *src_dir, Buf *src_basename, Buf *sou
if (g->verbose) {
fprintf(stderr, "\nCode Generation:\n");
fprintf(stderr, "------------------\n");
}
do_code_gen(g);