-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfunc_def.cpp
88 lines (71 loc) · 2.35 KB
/
func_def.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#include "func_def.hpp"
#include <llvm/IR/BasicBlock.h>
#include <llvm/IR/Verifier.h>
#include <cassert>
func_def::func_def(declaration_specs *decl_specs, declarator_node *declarator,
compound_stmt *statement) {
this->decl_specs = decl_specs;
this->declarator = declarator;
this->statement = statement;
this->func_decl = declarator->get_func_decl();
if (!this->func_decl) {
raise_error("Function definition does not contain a function declarator");
}
}
void func_def::old_style_error() {
print_warning("Old-style (K&R) function definition is not supported.");
}
void func_def::dump_tree() {
cout << "- (function_definition)" << endl;
cout.indent();
decl_specs->dump_tree();
declarator->dump_tree();
statement->dump_tree();
cout.unindent();
}
void func_def::codegen() {
llvm::Function *func = func_decl->codegen_def(decl_specs->get_type());
statement->codegen();
llvm::BasicBlock *insert_block = ir_builder.GetInsertBlock();
// insert_block is not terminated due to our invariant
assert(!insert_block->getTerminator() && "Block should not be terminated");
if (insert_block->empty() && insert_block->use_empty()) {
// Empty basic block with no uses. Remove it
insert_block->eraseFromParent();
} else if (!decl_specs->get_type().llvm_type->isVoidTy()) {
print_warning("No return statement in function with non-void return type");
ir_builder.CreateRet(llvm::UndefValue::get(func->getReturnType()));
} else { // Void type
ir_builder.CreateRetVoid();
}
// The function scope would've been added by codegen_def of func_decl
sym_table.pop_func_scope();
/* for (auto &block : func->getBasicBlockList()) {
block.print(llvm::outs());
} */
llvm::verifyFunction(*func); // TODO: Print debugging info from here
}
trans_unit *trans_unit::add(external_decl *decl) {
external_decls.push_back(decl);
return this;
}
void trans_unit::dump_tree() {
cout << "- (translation_unit)" << endl;
cout.indent();
for (auto &decl : external_decls) {
decl->dump_tree();
}
cout.unindent();
}
void trans_unit::codegen() {
for (auto decl : external_decls) {
decl->codegen();
}
if (!the_module->getFunction("main")) {
raise_error("'main' function not defined!");
}
if (llvm::verifyModule(*the_module, &llvm::errs())) {
the_module->print(llvm::errs(), nullptr);
return;
}
}