1
2
3
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& formatter, Context& 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, *this, context);
99 }
100 formatter.DecIndent();
101 formatter.WriteLine("}");
102 }
103
104 }