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;