#ifndef PCC_CONTEXT_H #define PCC_CONTEXT_H #include #include #include #include #include "TypeManager.hh" #include "VariableList.hh" namespace pcc { using Function = std::pair, 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 scopes_; std::unordered_map Functions_; std::stack BreakDestinations_; std::stack 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