summaryrefslogtreecommitdiff
path: root/Context.hh
blob: 7829dcf1323ca00b1dd9e19172d6b49dacd09fad (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#ifndef PCC_CONTEXT_H
#define PCC_CONTEXT_H

#include <stack>
#include <unordered_map>

#include <llvm/IR/IRBuilder.h>
#include <llvm/IR/Module.h>

#include "TypeManager.hh"
#include "VariableList.hh"

namespace pcc {
using Function = std::pair<std::shared_ptr<FunctionType>, llvm::Function*>;

class Context {
  public:
    Context(const char* name);
    TypeManager* GetTypeManager();
    VariableList* GetGlobals();
    llvm::Module* GetModule();
    llvm::IRBuilder<>* GetBuilder();
    VariableList* GetCurrentScope();
    void PushScope(VariableList* scope);
    void PopScope();
    Function FindFunction(std::string name);
    void AddFunction(std::string name, Function func);

    // every time we enter a while, repeat or for statement, we push the
    // destination of break and continue.
    void PushBreakDestination(llvm::BasicBlock* dest);
    void PopBreakDestination();
    llvm::BasicBlock* GetBreakDestination();
    void PushContinueDestination(llvm::BasicBlock* dest);
    void PopContinueDestination();
    llvm::BasicBlock* GetContinueDestination();
    void SetJumpingFlag(bool flag);
    bool GetJumpingFlag();

  private:
    llvm::IRBuilder<> builder_;
    llvm::Module module_;
    TypeManager TypeManager_;
    VariableList globals_;
    std::stack<VariableList*> scopes_;
    std::unordered_map<std::string, Function> Functions_;
    std::stack<llvm::BasicBlock*> BreakDestinations_;
    std::stack<llvm::BasicBlock*> ContinueDestinations_;
    // if statments always link then and else block with the endif block, it
    // assumes that no instruction will jump out from the body. break and
    // continue break this assumption, which makes IfStatementNode creates extra
    // br instructions, and LLVM will complain "No predecessors!". we use this
    // flag to tell IfStatementNode if there is a break or continue inside it.
    bool JumpingFlag_;
};

extern llvm::LLVMContext GlobalLLVMContext;
} // namespace pcc

#endif