From 9f1d1628cf4634f8e964a3f32590493e421baae6 Mon Sep 17 00:00:00 2001 From: Su Xing Date: Thu, 23 Mar 2023 17:03:44 +0800 Subject: [PATCH] IR and IRBuilder implementation. --- src/IR.cpp | 99 +++++++++++++++++++++++++++++++++++++++++++++++++ src/IRBuilder.h | 97 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 196 insertions(+) create mode 100644 src/IR.cpp create mode 100644 src/IRBuilder.h diff --git a/src/IR.cpp b/src/IR.cpp new file mode 100644 index 0000000..13de99d --- /dev/null +++ b/src/IR.cpp @@ -0,0 +1,99 @@ +#include "IR.h" +#include +#include +#include +#include +#include +#include +#include +#include + +namespace std { + +//===----------------------------------------------------------------------===// +// Types +//===----------------------------------------------------------------------===// + +template <> struct hash { + size_t operator()(const sysy::FunctionType &type) { + auto num = 1 + type.getNumParams(); + vector buffer(1, type.getReturnType()); + copy(type.getParamTypes().begin(), type.getParamTypes().end(), + back_inserter(buffer)); + string bytes(reinterpret_cast(buffer.data()), + buffer.size() * sizeof(sysy::Type *)); + hash hasher; + return hasher(bytes); + } +}; + +} // namespace std + +namespace sysy { + +Type *Type::getIntType() { + static Type intType(kInt); + return &intType; +} + +Type *Type::getFloatType() { + static Type floatType(kFloat); + return &floatType; +} + +Type *Type::getVoidType() { + static Type voidType(kVoid); + return &voidType; +} + +Type *Type::getLabelType() { + static Type labelType(kLabel); + return &labelType; +} + +Type *Type::getPointerType(Type *baseType) { + // forward to PointerType + return PointerType::get(baseType); +} + +Type *Type::getFunctionType(Type *returnType, + const std::vector ¶mTypes) { + // forward to FunctionType + return FunctionType::get(returnType, paramTypes); +} + +PointerType *PointerType::get(Type *baseType) { + static std::map pointerTypes; + auto result = pointerTypes.try_emplace(baseType, baseType); + return &(result.first->second); +} + +FunctionType *FunctionType::get(Type *returnType, + const std::vector ¶mTypes) { + static std::unordered_set functionTypes; + auto result = functionTypes.emplace(returnType, paramTypes); + // STL set objects are immutable, sothe emplace method returns const_iterator. + // We are sure FunctionType pointers cannot be used to mutate the underlying + // FunctionType object because all FunctionType methods are const methods. + return const_cast(&(*result.first)); +} + +void Value::replaceAllUsesWith(Value *value) { + for (auto &use : uses) + use->getUser()->setOperand(use->getIndex(), value); + uses.clear(); +} + +void User::setOperand(int index, Value *value) { + assert(index < getNumOperands()); + operands[index].setValue(value); +} + +void User::replaceOperand(int index, Value *value) { + assert(index < getNumOperands()); + auto &use = operands[index]; + use.getValue()->removeUse(&use); + use.setValue(value); +} + +} // namespace sysy \ No newline at end of file diff --git a/src/IRBuilder.h b/src/IRBuilder.h new file mode 100644 index 0000000..3608b6b --- /dev/null +++ b/src/IRBuilder.h @@ -0,0 +1,97 @@ +#pragma once + +#include "IR.h" +#include +#include + +namespace sysy { + +class IRBuilder { +private: + BasicBlock *block; + BasicBlock::iterator position; + +public: + IRBuilder(BasicBlock *block) : block(block), position(block->end()) {} + IRBuilder(BasicBlock *block, BasicBlock::iterator position) + : block(block), position(position) {} + +public: + BasicBlock *getBasicBlock() const { return block; } + BasicBlock::iterator getPosition() const { return position; } + void setPosition(BasicBlock::iterator position) { this->position = position; } + +public: + CallInst *createCallInst(Function *callee, + const std::vector args = {}, + const std::string &name = "") { + auto inst = new CallInst(callee, args, block, name); + assert(inst); + block->getInstructions().emplace(position, inst); + return inst; + } + UnaryInst *createUnaryInst(Instruction::Kind kind, Type *type, Value *operand, + const std::string &name = "") { + + auto inst = new UnaryInst(kind, type, operand, block, name); + assert(inst); + block->getInstructions().emplace(position, inst); + return inst; + } + BinaryInst *createBinaryInst(Instruction::Kind kind, Type *type, Value *lhs, + Value *rhs, const std::string &name = "") { + auto inst = new BinaryInst(kind, type, lhs, rhs, block, name); + assert(inst); + block->getInstructions().emplace(position, inst); + return inst; + } + ReturnInst *createReturnInst(Value *value = nullptr) { + auto inst = new ReturnInst(value); + assert(inst); + block->getInstructions().emplace(position, inst); + return inst; + } + UncondBrInst *createUncondBrInst(BasicBlock *block, + std::vector args) { + auto inst = new UncondBrInst(block, args, block); + assert(inst); + block->getInstructions().emplace(position, inst); + return inst; + } + CondBrInst *createCondBrInst(Value *condition, BasicBlock *thenBlock, + BasicBlock *elseBlock, + const std::vector &thenArgs, + const std::vector &elseArgs) { + auto inst = new CondBrInst(condition, thenBlock, elseBlock, thenArgs, + elseArgs, block); + assert(inst); + block->getInstructions().emplace(position, inst); + return inst; + } + AllocaInst *createAllocaInst(Type *type, + const std::vector &dims = {}, + const std::string &name = "") { + auto inst = new AllocaInst(type, dims, block, name); + assert(inst); + block->getInstructions().emplace(position, inst); + return inst; + } + LoadInst *createLoadInst(Value *pointer, + const std::vector &indices = {}, + const std::string &name = "") { + auto inst = new LoadInst(pointer, indices, block, name); + assert(inst); + block->getInstructions().emplace(position, inst); + return inst; + } + StoreInst *createStoreInst(Value *value, Value *pointer, + const std::vector &indices = {}, + const std::string &name = "") { + auto inst = new StoreInst(value, pointer, indices, block, name); + assert(inst); + block->getInstructions().emplace(position, inst); + return inst; + } +}; + +} // namespace sysy \ No newline at end of file