Commit 52615882 authored by Yang's avatar Yang

pulish lab2

parent 5e3c0318
...@@ -30,6 +30,7 @@ class BasicBlock : public Value, public llvm::ilist_node<BasicBlock> { ...@@ -30,6 +30,7 @@ class BasicBlock : public Value, public llvm::ilist_node<BasicBlock> {
void add_succ_basic_block(BasicBlock *bb) { succ_bbs_.push_back(bb); } void add_succ_basic_block(BasicBlock *bb) { succ_bbs_.push_back(bb); }
void remove_pre_basic_block(BasicBlock *bb) { pre_bbs_.remove(bb); } void remove_pre_basic_block(BasicBlock *bb) { pre_bbs_.remove(bb); }
void remove_succ_basic_block(BasicBlock *bb) { succ_bbs_.remove(bb); } void remove_succ_basic_block(BasicBlock *bb) { succ_bbs_.remove(bb); }
BasicBlock* get_entry_block_of_same_function();
// If the Block is terminated by ret/br // If the Block is terminated by ret/br
bool is_terminated() const; bool is_terminated() const;
......
...@@ -46,6 +46,8 @@ class Function : public Value, public llvm::ilist_node<Function> { ...@@ -46,6 +46,8 @@ class Function : public Value, public llvm::ilist_node<Function> {
void set_instr_name(); void set_instr_name();
std::string print(); std::string print();
// 用于检查函数的基本块是否存在问题
void check_for_block_relation_error();
private: private:
llvm::ilist<BasicBlock> basic_blocks_; llvm::ilist<BasicBlock> basic_blocks_;
......
...@@ -86,6 +86,9 @@ class IRBuilder { ...@@ -86,6 +86,9 @@ class IRBuilder {
AllocaInst *create_alloca(Type *ty) { AllocaInst *create_alloca(Type *ty) {
return AllocaInst::create_alloca(ty, this->BB_); return AllocaInst::create_alloca(ty, this->BB_);
} }
AllocaInst *create_alloca_begin(Type *ty) {
return AllocaInst::create_alloca_begin(ty, this->BB_);
}
ZextInst *create_zext(Value *val, Type *ty) { ZextInst *create_zext(Value *val, Type *ty) {
return ZextInst::create_zext(val, ty, this->BB_); return ZextInst::create_zext(val, ty, this->BB_);
} }
......
...@@ -289,6 +289,7 @@ class AllocaInst : public BaseInst<AllocaInst> { ...@@ -289,6 +289,7 @@ class AllocaInst : public BaseInst<AllocaInst> {
public: public:
static AllocaInst *create_alloca(Type *ty, BasicBlock *bb); static AllocaInst *create_alloca(Type *ty, BasicBlock *bb);
static AllocaInst *create_alloca_begin(Type *ty, BasicBlock *bb);
Type *get_alloca_type() const { Type *get_alloca_type() const {
return get_type()->get_pointer_element_type(); return get_type()->get_pointer_element_type();
......
...@@ -95,9 +95,11 @@ void Config::check() { ...@@ -95,9 +95,11 @@ void Config::check() {
if (input_file.empty()) { if (input_file.empty()) {
print_err("no input file"); print_err("no input file");
} }
/*
if (input_file.extension() != ".cminus") { if (input_file.extension() != ".cminus") {
print_err("file format not recognized"); print_err("file format not recognized");
} }
*/
if (output_file.empty()) { if (output_file.empty()) {
output_file = input_file.stem(); output_file = input_file.stem();
} }
......
...@@ -69,3 +69,8 @@ std::string BasicBlock::print() { ...@@ -69,3 +69,8 @@ std::string BasicBlock::print() {
return bb_ir; return bb_ir;
} }
BasicBlock* BasicBlock::get_entry_block_of_same_function(){
assert((not (parent_ == nullptr)) && "bb have no parent function");
return parent_->get_entry_block();
}
\ No newline at end of file
#include "Function.hpp" #include "Function.hpp"
#include "IRprinter.hpp" #include "IRprinter.hpp"
#include "Module.hpp" #include "Module.hpp"
#include "Instruction.hpp"
#include <cassert>
#include <unordered_set>
#include <queue>
Function::Function(FunctionType *ty, const std::string &name, Module *parent) Function::Function(FunctionType *ty, const std::string &name, Module *parent)
: Value(ty, name), parent_(parent), seq_cnt_(0) { : Value(ty, name), parent_(parent), seq_cnt_(0) {
...@@ -129,3 +133,103 @@ std::string Argument::print() { ...@@ -129,3 +133,103 @@ std::string Argument::print() {
arg_ir += this->get_name(); arg_ir += this->get_name();
return arg_ir; return arg_ir;
} }
void Function::check_for_block_relation_error()
{
// 检查函数的基本块表是否包含所有且仅包含 get_parent 是本函数的基本块
std::unordered_set<BasicBlock*> bbs;
for (auto& bb : basic_blocks_)
{
bbs.emplace(&bb);
}
for (auto& bb : basic_blocks_)
{
assert((bb.get_parent() == this) && "函数 F 的基本块表中包含基本块 a, 但 a 的 get_parent 方法不返回 F");
for (auto i: bb.get_succ_basic_blocks())
{
assert((bbs.count(i)) && "函数 F 的基本块表中包含基本块 a, a 的后继块表中的某基本块 b 不在 F 的基本块表中");
}
for (auto i: bb.get_pre_basic_blocks())
{
assert((bbs.count(i)) && "函数 F 的基本块表中包含基本块 a, a 的前驱块表中的某基本块 b 不在 F 的基本块表中");
}
}
// 检查基本块的前驱和后继表不包含重复的基本块
for (auto& bb : basic_blocks_)
{
bbs.clear();
for(auto suc: bb.get_succ_basic_blocks()){
assert((!bbs.count(suc)) && "基本块的后继表中包含重复项目");
bbs.emplace(suc);
}
for(auto suc: bb.get_pre_basic_blocks()){
assert((!bbs.count(suc)) && "基本块的前驱表中包含重复项目");
bbs.emplace(suc);
}
}
// 检查基本块基本信息
for (auto& bb : basic_blocks_)
{
assert((!bb.get_instructions().empty()) && "发现了空基本块");
auto b = &bb.get_instructions().back();
assert((b->is_br() || b->is_ret()) && "发现了无 terminator 基本块");
assert((b->is_br() || bb.get_succ_basic_blocks().empty()) && "某基本块末尾是 ret 指令但是后继块表不是空的, 或者末尾是 br 但后继表为空");
}
// 检查基本块前驱后继关系是否是与 branch 指令对应
for (auto& bb : basic_blocks_)
{
if(!bb.get_succ_basic_blocks().empty()){
std::unordered_set<BasicBlock*> suc_table;
std::unordered_set<BasicBlock*> br_get;
for (auto suc : bb.get_succ_basic_blocks())
suc_table.emplace(suc);
auto& ops = bb.get_instructions().back().get_operands();
for (auto i : ops)
{
auto bb2 = dynamic_cast<BasicBlock*>(i);
if(bb2 != nullptr) br_get.emplace(bb2);
}
for(auto i : suc_table)
assert(br_get.count(i) && "基本块 A 的后继块有 B,但 B 并未在 A 的 br 指令中出现");
for(auto i : br_get)
assert(suc_table.count(i) && "基本块 A 的后继块没有 B,但 B 在 A 的 br 指令中出现了");
for(auto i : suc_table) {
bool ok = false;
for(auto j : i->get_pre_basic_blocks()) {
if(j == i){
ok = true;
break;
}
}
assert(ok && "基本块 A 的后继块表中有 B,但 B 的前驱表中没有 A");
}
}
}
// 检查基本块前驱后继关系是否是与 branch 指令对应
for (auto& bb : basic_blocks_)
{
for (auto pre : bb.get_pre_basic_blocks())
{
bool ok = false;
for (auto i : pre->get_succ_basic_blocks())
{
if (i == &bb)
{
ok = true;
break;
}
}
if (!ok)
assert(false && "基本块 A 的后继块表中没有 B,但 B 的前驱表中有 A");
}
}
// 检查指令 parent 设置
for (auto& bb : basic_blocks_)
{
for (auto& inst : bb.get_instructions())
{
assert ((inst.get_parent() == &bb) && "基本块 A 指令表包含指令 b, 但是 b 的 get_parent 函数不返回 A");
}
}
}
...@@ -298,6 +298,16 @@ AllocaInst *AllocaInst::create_alloca(Type *ty, BasicBlock *bb) { ...@@ -298,6 +298,16 @@ AllocaInst *AllocaInst::create_alloca(Type *ty, BasicBlock *bb) {
return create(ty, bb); return create(ty, bb);
} }
AllocaInst *AllocaInst::create_alloca_begin(Type *ty, BasicBlock *bb) {
auto ret = create(ty, nullptr);
if(bb != nullptr)
{
ret->set_parent(bb);
bb->add_instr_begin(ret);
}
return ret;
}
ZextInst::ZextInst(Value *val, Type *ty, BasicBlock *bb) ZextInst::ZextInst(Value *val, Type *ty, BasicBlock *bb)
: BaseInst<ZextInst>(ty, zext, bb) { : BaseInst<ZextInst>(ty, zext, bb) {
assert(val->get_type()->is_integer_type() && assert(val->get_type()->is_integer_type() &&
......
void main(void) {
int i;
i = 0;
while (i < 16384) {
int a[16384];
a[1] = i;
i = i + 1;
}
output(0);
return;
}
@x = global [1 x i32] zeroinitializer
@y = global [1 x i32] zeroinitializer
define i32 @gcd(i32 %0, i32 %1) {
%3 = alloca i32
%4 = alloca i32
%5 = alloca i32
store i32 %0, i32* %4
store i32 %1, i32* %5
%6 = load i32, i32* %5
%7 = icmp eq i32 %6, 0
br i1 %7, label %8, label %10
8:
%9 = load i32, i32* %4
store i32 %9, i32* %3
br label %20
10:
%11 = load i32, i32* %5
%12 = load i32, i32* %4
%13 = load i32, i32* %4
%14 = load i32, i32* %5
%15 = sdiv i32 %13, %14
%16 = load i32, i32* %5
%17 = mul i32 %15, %16
%18 = sub i32 %12, %17
%19 = call i32 @gcd(i32 %11, i32 %18)
store i32 %19, i32* %3
br label %20
20:
%21 = load i32, i32* %3
ret i32 %21
}
define i32 @funArray(i32* %0, i32* %1) {
%3 = alloca i32*
%4 = alloca i32*
%5 = alloca i32
%6 = alloca i32
%7 = alloca i32
store i32* %0, i32** %3
store i32* %1, i32** %4
%8 = load i32*, i32** %3
%9 = getelementptr i32, i32* %8, i64 0
%10 = load i32, i32* %9
store i32 %10, i32* %5
%11 = load i32*, i32** %4
%12 = getelementptr i32, i32* %11, i64 0
%13 = load i32, i32* %12
store i32 %13, i32* %6
%14 = load i32, i32* %5
%15 = load i32, i32* %6
%16 = icmp slt i32 %14, %15
br i1 %16, label %17, label %21
17:
%18 = load i32, i32* %5
store i32 %18, i32* %7
%19 = load i32, i32* %6
store i32 %19, i32* %5
%20 = load i32, i32* %7
store i32 %20, i32* %6
br label %21
21:
%22 = load i32, i32* %5
%23 = load i32, i32* %6
%24 = call i32 @gcd(i32 %22, i32 %23)
ret i32 %24
}
define i32 @main() {
%1 = alloca i32
store i32 0, i32* %1
%2 = getelementptr [1 x i32], [1 x i32]* @x, i64 0, i64 0
store i32 90, i32* %2
%3 = getelementptr [1 x i32], [1 x i32]* @y, i64 0, i64 0
store i32 18, i32* %3
%4 = getelementptr [1 x i32], [1 x i32]* @x, i64 0, i64 0
%5 = getelementptr [1 x i32], [1 x i32]* @y, i64 0, i64 0
%6 = call i32 @funArray(i32* %4, i32* %5)
ret i32 %6
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment