forked from ph7n2ofui/SysyCompiler_Arm
parent
28b30ce258
commit
9f1d1628cf
@ -0,0 +1,99 @@
|
||||
#include "IR.h"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <iterator>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
namespace std {
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Types
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
template <> struct hash<sysy::FunctionType> {
|
||||
size_t operator()(const sysy::FunctionType &type) {
|
||||
auto num = 1 + type.getNumParams();
|
||||
vector<sysy::Type *> buffer(1, type.getReturnType());
|
||||
copy(type.getParamTypes().begin(), type.getParamTypes().end(),
|
||||
back_inserter(buffer));
|
||||
string bytes(reinterpret_cast<char *>(buffer.data()),
|
||||
buffer.size() * sizeof(sysy::Type *));
|
||||
hash<string> 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<Type *> ¶mTypes) {
|
||||
// forward to FunctionType
|
||||
return FunctionType::get(returnType, paramTypes);
|
||||
}
|
||||
|
||||
PointerType *PointerType::get(Type *baseType) {
|
||||
static std::map<Type *, PointerType> pointerTypes;
|
||||
auto result = pointerTypes.try_emplace(baseType, baseType);
|
||||
return &(result.first->second);
|
||||
}
|
||||
|
||||
FunctionType *FunctionType::get(Type *returnType,
|
||||
const std::vector<Type *> ¶mTypes) {
|
||||
static std::unordered_set<FunctionType> 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<FunctionType *>(&(*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
|
||||
@ -0,0 +1,97 @@
|
||||
#pragma once
|
||||
|
||||
#include "IR.h"
|
||||
#include <cassert>
|
||||
#include <memory>
|
||||
|
||||
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<Value *> 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<Value *> 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<Value *> &thenArgs,
|
||||
const std::vector<Value *> &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<Value *> &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<Value *> &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<Value *> &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
|
||||
Loading…
Reference in new issue