3 #include <forward_list>
6 #include "tir/Instructions.h"
9 #include "utils/Generator.h"
10 #include "utils/Utils.h"
25 virtual bool isNullPointer()
const {
return false; }
26 virtual bool isNumeric()
const {
return false; }
27 virtual bool isBoolean()
const {
return false; }
30 static ConstantInt* CreateInt(
Context& ctx, uint8_t bits, uint32_t value);
31 static ConstantInt* CreateBool(
Context& ctx,
bool value) {
32 return CreateInt(ctx, 1, value ? 1 : 0);
34 static ConstantInt* CreateInt32(
Context& ctx, uint32_t value) {
35 return CreateInt(ctx, 32, value);
37 static ConstantNullPointer* CreateNullPointer(
Context& ctx);
45 ConstantInt(
Context& ctx,
Type* type, uint64_t value)
46 :
Constant{ctx, type}, value_{value} {}
49 static ConstantInt* Create(
Context& ctx,
Type* type, uint64_t value) {
50 assert(type->isIntegerType() &&
"Type must be an integer type");
52 ctx.alloc().allocate_bytes(
sizeof(ConstantInt),
alignof(ConstantInt));
53 return new(buf) ConstantInt{ctx, type, value};
55 static ConstantInt* AllOnes(
Context& ctx,
Type* type) {
56 return Create(ctx, type, ~0ULL);
58 static ConstantInt* Zero(
Context& ctx,
Type* type) {
59 return Create(ctx, type, 0);
63 std::ostream& print(std::ostream& os)
const override;
64 uint64_t zextValue()
const {
65 return value_ & cast<IntegerType>(type())->getMask();
67 uint64_t sextValue()
const {
68 auto mask = cast<IntegerType>(type())->getMask();
69 return (value_ & mask) |
70 ((value_ & (1ULL << (type()->getSizeInBits() - 1))) ? ~mask : 0);
72 bool isNumeric()
const override {
return true; }
73 bool isBoolean()
const override {
return type()->isBooleanType(); }
82 class ConstantNullPointer
final :
public Constant {
88 static ConstantNullPointer* Create(
Context& ctx) {
89 return ctx.pimpl().nullPointer;
93 std::ostream& print(std::ostream& os)
const override;
94 bool isNullPointer()
const override {
return true; }
105 virtual bool isExternalLinkage()
const = 0;
118 std::ostream& print(std::ostream& os)
const override;
119 bool isExternalLinkage()
const override {
return false; }
125 class Argument
final :
public Value {
126 friend class Function;
129 Argument(Function* parent,
Type* type,
unsigned index);
132 std::ostream& print(std::ostream& os)
const override;
133 auto* parent()
const {
return parent_; }
134 auto index()
const {
return index_; }
146 friend class BasicBlock;
150 const std::string_view name)
151 :
GlobalObject{ctx, type}, body_{ctx.alloc()}, parent_{parent} {
155 for(
unsigned i = 0; i < type->numParams(); ++i) {
157 ctx.alloc().allocate_bytes(
sizeof(Argument),
alignof(Argument));
158 auto* arg =
new(buf) Argument{
this, type->getParamType(i), i};
164 std::ostream& print(std::ostream& os)
const override;
165 auto* parent()
const {
return parent_; }
167 return std::views::transform(
168 children(), [](
Value* val) {
return static_cast<Argument*>(val); });
170 auto numParams()
const {
return cast<FunctionType>(type())->numParams(); }
171 auto getParamType(
int index)
const {
172 return cast<FunctionType>(type())->getParamType(index);
174 auto getReturnType()
const {
175 return cast<FunctionType>(type())->getReturnType();
177 bool hasBody()
const {
return !body_.empty(); }
181 auto body()
const {
return std::views::all(body_); }
182 void removeBlock(BasicBlock* block) {
183 assert(block->parent() ==
this &&
"Block does not belong to this function");
184 assert(block != entryBB_ &&
"Cannot remove the entry block");
198 auto* inst = AllocaInst::Create(ctx(), type);
203 auto isNoReturn()
const {
return noReturn_; }
205 void setNoReturn() { noReturn_ =
true; }
207 void setExternalLinkage() { external_ =
true; }
209 bool isExternalLinkage()
const override {
210 if(!external_)
return !entryBB_;
214 void printDot(std::ostream& os)
const;
216 utils::
Generator<BasicBlock*> reversePostOrder()
const;
218 utils::
Generator<AllocaInst*> allocas()
const {
220 for(
auto* inst : *entryBB_) {
221 if(
auto* alloca = dyn_cast<AllocaInst>(inst)) {
229 void addBlock(BasicBlock* block) {
230 if(!entryBB_) entryBB_ = block;
231 body_.push_front(block);
235 std::pmr::forward_list<BasicBlock*> body_;
236 BasicBlock* entryBB_ =
nullptr;
238 bool noReturn_ =
false;
239 bool external_ =
false;