1 // =================================
  2 // Copyright (c) 2021 Seppo Laakko
  3 // Distributed under the MIT license
  4 // =================================
  5 
  6 #include <cmajor/cmsxi/Function.hpp>
  7 #include <cmajor/cmsxi/Context.hpp>
  8 #include <soulng/util/Error.hpp>
  9 
 10 namespace cmsxi {
 11 
 12 Function::Function(const std::string& name_FunctionType* type_Context& context) : Value()name(name_)type(type_)nextResultNumber(0)linkOnce(false)mdId(-1)nextBBNumber(0)
 13 {
 14     entryBlock.reset(new BasicBlock(nextBBNumber++));
 15     for (Type* paramType : type->ParamTypes())
 16     {
 17         Instruction* paramInst = new ParamInstruction(paramType);
 18         context.AddLineInfo(paramInst);
 19         entryBlock->AddInstruction(paramInst);
 20         params.push_back(paramInst);
 21     }
 22 }
 23 
 24 BasicBlock* Function::CreateBasicBlock()
 25 {
 26     if (basicBlocks.empty())
 27     {
 28         BasicBlock* bb = entryBlock.get();
 29         basicBlocks.push_back(std::move(entryBlock));
 30         return bb;
 31     }
 32     BasicBlock* bb = new BasicBlock(nextBBNumber++);
 33     basicBlocks.push_back(std::unique_ptr<BasicBlock>(bb));
 34     return bb;
 35 }
 36 
 37 BasicBlock* Function::CreateCleanupBasicBlock()
 38 {
 39     BasicBlock* cubb = new BasicBlock(-1);
 40     cleanupBasicBlocks.push_back(std::unique_ptr<BasicBlock>(cubb));
 41     return cubb;
 42 }
 43 
 44 void Function::Finalize()
 45 {
 46     nextBBNumber = 0;
 47     for (std::std::unique_ptr<BasicBlock>&cubb : cleanupBasicBlocks)
 48     {
 49         basicBlocks.push_back(std::move(cubb));
 50     }
 51     for (auto& bb : basicBlocks)
 52     {
 53         if (bb->IsEmpty())
 54         {
 55             continue;
 56         }
 57         bb->SetId(nextBBNumber++);
 58     }
 59 }
 60 
 61 Value* Function::GetParam(int index) const
 62 {
 63     Assert(index >= 0 && index < params.size()"invalid param index");
 64     return params[index];
 65 }
 66 
 67 void Function::Write(CodeFormatter& formatterContext& context)
 68 {
 69     if (basicBlocks.empty()) return;
 70     std::string once;
 71     if (linkOnce)
 72     {
 73         once = " once";
 74     }
 75     std::string mdIdStr;
 76     if (mdId != -1)
 77     {
 78         mdIdStr = " !" + std::to_string(mdId);
 79     }
 80     formatter.WriteLine("function " + type->Name() + once + " " + name + mdIdStr);
 81     formatter.WriteLine("{");
 82     formatter.IncIndent();
 83     bool first = true;
 84     for (const auto& bb : basicBlocks)
 85     {
 86         if (bb->IsEmpty())
 87         {
 88             continue;
 89         }
 90         if (first)
 91         {
 92             first = false;
 93         }
 94         else
 95         {
 96             formatter.WriteLine();
 97         }
 98         bb->Write(formatter*thiscontext);
 99     }
100     formatter.DecIndent();
101     formatter.WriteLine("}");
102 }
103 
104 } // namespace cmsxi