1 // =================================
  2 // Copyright (c) 2021 Seppo Laakko
  3 // Distributed under the MIT license
  4 // =================================
  5 
  6 #ifndef CMAJOR_CODEGENLLVM_LLVMCODEGENERATOR_INCLUDED
  7 #define CMAJOR_CODEGENLLVM_LLVMCODEGENERATOR_INCLUDED
  8 #include <cmajor/codegenllvm/CodeGenLlvmApi.hpp>
  9 #include <cmajor/codegenbase/CodeGenerator.hpp>
 10 #include <cmajor/ir/Emitter.hpp>
 11 #include <cmajor/binder/BoundNodeVisitor.hpp>
 12 #include <cmajor/symbols/SymbolTable.hpp>
 13 #include <cmajor/binder/BoundClass.hpp>
 14 #include <cmajor/binder/BoundStatement.hpp>
 15 
 16 namespace cmajor { namespace codegenllvm {
 17 
 18 using namespace cmajor::binder;
 19 
 20 struct Cleanup 
 21 {
 22     Cleanup(void* cleanupBlock_void* handlerBlock_Pad* currentPad_) : cleanupBlock(cleanupBlock_)handlerBlock(handlerBlock_)currentPad(currentPad_) {}
 23     void* cleanupBlock;
 24     void* handlerBlock;
 25     Pad* currentPad;
 26     std::vector<std::std::unique_ptr<BoundFunctionCall>>destructors;
 27 };
 28 
 29 class LlvmCodeGenerator public cmajor::codegenbase::CodeGeneratorpublic BoundNodeVisitorpublic cmajor::ir::EmittingDelegate
 30 {
 31 public:
 32     LlvmCodeGenerator(cmajor::ir::EmittingContext& emittingContext_);
 33     LlvmCodeGenerator(const LlvmCodeGenerator&) = delete;
 34     LlvmCodeGenerator& operator=(const LlvmCodeGenerator&) = delete;
 35     void GenerateCode(void* boundCompileUnit) override;
 36     void Visit(BoundCompileUnit& boundCompileUnit) override;
 37     void Visit(BoundNamespace& boundNamespace) override;
 38     void Visit(BoundClass& boundClass) override;
 39     void Visit(BoundEnumTypeDefinition& boundEnumTypeDefinition) override;
 40     void Visit(BoundFunction& boundFunction) override;
 41     void Visit(BoundSequenceStatement& boundSequenceStatement) override;
 42     void Visit(BoundCompoundStatement& boundCompoundStatement) override;
 43     void Visit(BoundIfStatement& boundIfStatement) override;
 44     void Visit(BoundWhileStatement& boundWhileStatement) override;
 45     void Visit(BoundDoStatement& boundDoStatement) override;
 46     void Visit(BoundForStatement& boundForStatement) override;
 47     void Visit(BoundSwitchStatement& boundSwitchStatement) override;
 48     void Visit(BoundCaseStatement& boundCaseStatement) override;
 49     void Visit(BoundDefaultStatement& boundDefaultStatement) override;
 50     void Visit(BoundConstructionStatement& boundConstructionStatement) override;
 51     void Visit(BoundAssignmentStatement& boundAssignmentStatement) override;
 52     void Visit(BoundExpressionStatement& boundExpressionStatement) override;
 53     void Visit(BoundInitializationStatement& boundInitializationStatement) override;
 54     void Visit(BoundEmptyStatement& boundEmptyStatement) override;
 55     void Visit(BoundSetVmtPtrStatement& boundSetVmtPtrStatement) override;
 56     void Visit(BoundThrowStatement& boundThrowStatement) override;
 57     void Visit(BoundParameter& boundParameter) override;
 58     void Visit(BoundLocalVariable& boundLocalVariable) override;
 59     void Visit(BoundMemberVariable& boundMemberVariable) override;
 60     void Visit(BoundConstant& boundConstant) override;
 61     void Visit(BoundEnumConstant& boundEnumConstant) override;
 62     void Visit(BoundLiteral& boundLiteral) override;
 63     void Visit(BoundTemporary& boundTemporary) override;
 64     void Visit(BoundSizeOfExpression& boundSizeOfExpression) override;
 65     void Visit(BoundAddressOfExpression& boundAddressOfExpression) override;
 66     void Visit(BoundDereferenceExpression& boundDereferenceExpression) override;
 67     void Visit(BoundReferenceToPointerExpression& boundReferenceToPointerExpression) override;
 68     void Visit(BoundFunctionCall& boundFunctionCall) override;
 69     void Visit(BoundDelegateCall& boundDelegateCall) override;
 70     void Visit(BoundClassDelegateCall& boundClassDelegateCall) override;
 71     void Visit(BoundConversion& boundConversion) override;
 72     void Visit(BoundConstructExpression& boundConstructExpression) override;
 73     void Visit(BoundConstructAndReturnTemporaryExpression& boundConstructAndReturnTemporaryExpression) override;
 74     void Visit(BoundClassOrClassDelegateConversionResult& boundClassOrClassDelegateConversionResult) override;
 75     void Visit(BoundIsExpression& boundIsExpression) override;
 76     void Visit(BoundAsExpression& boundAsExpression) override;
 77     void Visit(BoundTypeNameExpression& boundTypeNameExpression) override;
 78     void Visit(BoundBitCast& boundBitCast) override;
 79     void Visit(BoundFunctionPtr& boundFunctionPtr) override;
 80     void Visit(BoundDisjunction& boundDisjunction) override;
 81     void Visit(BoundConjunction& boundConjunction) override;
 82     void Visit(BoundGlobalVariable& boundGlobalVariable) override;
 83     void* GetGlobalStringPtr(int stringId) override;
 84     void* GetGlobalWStringConstant(int stringId) override;
 85     void* GetGlobalUStringConstant(int stringId) override;
 86     void* GetGlobalUuidConstant(int uuidId) override;
 87     void SetLineNumber(int32_t lineNumber) override;
 88     void* HandlerBlock() override;
 89     void* CleanupBlock() override;
 90     bool NewCleanupNeeded() override;
 91     std::string GetSourceFilePath(const Span& spanconst boost::uuids::uuid& moduleId) override;
 92     cmajor::ir::Pad* CurrentPad() override;
 93     void* CreateClassDIType(void* classPtr) override;
 94     void CreateExitFunctionCall();
 95     void GenerateEnterFunctionCode(BoundFunction& boundFunction);
 96     void GenerateExitFunctionCode(BoundFunction& boundFunction);
 97     void GenerateInitUnwindInfoFunction(BoundCompileUnit& boundCompileUnit);
 98     void GenerateInitCompileUnitFunction(BoundCompileUnit& boundCompileUnit);
 99     void GenerateGlobalInitFuncion(BoundCompileUnit& boundCompileUnit);
100     virtual void* GetPersonalityFunction() const = 0;
101     virtual void GenerateCodeForCleanups() = 0;
102     void SetTarget(BoundStatement* labeledStatement);
103     void ExitBlocks(BoundCompoundStatement* targetBlock);
104     void GenJumpingBoolCode();
105     void ClearFlags();
106     int Install(const std::string& str) override;
107     int Install(const std::u16string& str) override;
108     int Install(const std::u32string& str) override;
109     void MoveAllocaIntoEntryBlock(void* allocaInst);
110     void Optimize(int optimizationLevelconst std::string& bcFilePathconst std::string& optBCFilePath);
111     void* EntryBasicBlock() const { return entryBasicBlock; }
112 protected:
113     cmajor::symbols::SymbolTable* symbolTable;
114     cmajor::symbols::Module* symbolsModule;
115     cmajor::ir::Emitter* emitter;
116     cmajor::ir::EmittingContext* emittingContext;
117     void* module;
118     bool debugInfo;
119     BoundCompileUnit* compileUnit;
120     BoundClass* currentClass;
121     BoundFunction* currentFunction;
122     std::stack<BoundClass*> classStack;
123     std::unordered_map<intvoid*> utf8stringMap;
124     std::unordered_map<intvoid*> utf16stringMap;
125     std::unordered_map<intvoid*> utf32stringMap;
126     std::unordered_map<intvoid*> uuidMap;
127     void* trueBlock;
128     void* falseBlock;
129     void* breakTarget;
130     void* continueTarget;
131     void* handlerBlock;
132     void* cleanupBlock;
133     void* entryBasicBlock;
134     bool newCleanupNeeded;
135     Pad* currentPad;
136     int prevLineNumber;
137     bool destructorCallGenerated;
138     bool lastInstructionWasRet;
139     bool basicBlockOpen;
140     void* lastAlloca;
141     int compoundLevel;
142     std::string compileUnitId;
143     BoundStatement* sequenceSecond;
144     BoundCompoundStatement* currentBlock;
145     std::vector<std::std::unique_ptr<Cleanup>>cleanups;
146     std::vector<std::std::unique_ptr<Pad>>pads;
147     std::unordered_map<BoundStatement*void*> labeledStatementMap;
148     void* function;
149     std::unordered_map<BoundCompoundStatement*std::std::vector<std::std::unique_ptr<BoundFunctionCall>>>blockDestructionMap;
150     std::vector<BoundCompoundStatement*> blocks;
151     bool genJumpingBoolCode;
152     BoundCompoundStatement* breakTargetBlock;
153     BoundCompoundStatement* continueTargetBlock;
154     void* defaultDest;
155     std::std::unordered_map<IntegralValuevoid*IntegralValueHash>*currentCaseMap;
156     std::set<FunctionSymbol*> compileUnitFunctions;
157 };
158 
159 } } // namespace cmajor::codegen
160 
161 #endif // CMAJOR_CODEGENLLVM_LLVMCODEGENERATOR_INCLUDED