Nicolas Winkler 6 yıl önce
ebeveyn
işleme
f52286b388
7 değiştirilmiş dosya ile 223 ekleme ve 46 silme
  1. 77 15
      src/CodeGeneration.cpp
  2. 36 6
      src/CodeGeneration.h
  3. 44 4
      src/CodegenVisitor.cpp
  4. 19 3
      src/CodegenVisitor.h
  5. 10 7
      src/Semantic.cpp
  6. 23 8
      src/Semantic.h
  7. 14 3
      src/test.qlw

+ 77 - 15
src/CodeGeneration.cpp

@@ -36,20 +36,30 @@ std::unique_ptr<llvm::Module> generateModule(const sem::SymbolTable<sem::Class>&
     std::unique_ptr<Module> module = llvm::make_unique<Module>("qlow_module", context);
     
     std::vector<Type*> doubles(1, Type::getDoubleTy(context));
-    FunctionType* funcType = FunctionType::get(Type::getDoubleTy(context), doubles, false);
-    Function* func = Function::Create(funcType, Function::ExternalLinkage, "qlow_function", module.get());
-    BasicBlock* bb = BasicBlock::Create(context, "entry", func);
-    IRBuilder<> builder(context);
-    builder.SetInsertPoint(bb);
-
-    Function::arg_iterator args = func->arg_begin();
-
-    Argument* arg = &(*args);
-    
-    Value* val = llvm::ConstantFP::get(context, llvm::APFloat(5.0));
-    Value* val2 = llvm::ConstantFP::get(context, llvm::APFloat(1.0));
-    Value* result = builder.CreateFAdd(arg, val2, "add_constants");
-    builder.CreateRet(result);
+    for (auto& [name, cl] : classes){
+        for (auto& [name, method] : cl->methods) {
+
+            FunctionGenerator fg(*method, module.get());
+            fg.generate();
+
+            /*
+            FunctionType* funcType = FunctionType::get(Type::getDoubleTy(context), doubles, false);
+            Function* func = Function::Create(funcType, Function::ExternalLinkage, "qlow_function", module.get());
+            BasicBlock* bb = BasicBlock::Create(context, "entry", func);
+            IRBuilder<> builder(context);
+            builder.SetInsertPoint(bb);
+
+            Function::arg_iterator args = func->arg_begin();
+
+            Argument* arg = &(*args);
+            
+            Value* val = llvm::ConstantFP::get(context, llvm::APFloat(5.0));
+            Value* val2 = llvm::ConstantFP::get(context, llvm::APFloat(1.0));
+            Value* result = builder.CreateFAdd(arg, val2, "add_constants");
+            builder.CreateRet(result);
+            */
+        }
+    }
     return module;
 }
 
@@ -64,7 +74,10 @@ void generateObjectFile(const std::string& filename, std::unique_ptr<llvm::Modul
     using llvm::TargetOptions;
 
 
+    printf("verifying mod\n");
+    module->dump();
     llvm::verifyModule(*module);
+    printf("mod verified\n");
 
 
     llvm::InitializeAllTargetInfos();
@@ -145,7 +158,56 @@ void generateObjectFile(const std::string& filename, std::unique_ptr<llvm::Modul
   return 0;*/
 }
 
+} // namespace gen
+} // namespace qlow
+
+
+llvm::Function* qlow::gen::FunctionGenerator::generate(void)
+{
+    using llvm::Function;
+    using llvm::Argument;
+    using llvm::Type;
+    using llvm::FunctionType;
+    using llvm::BasicBlock;
+    using llvm::Value;
+    using llvm::IRBuilder;
+
+    std::vector<Type*> doubles(1, Type::getDoubleTy(context));
+    FunctionType* funcType = FunctionType::get(Type::getDoubleTy(context), doubles, false);
+    Function* func = Function::Create(funcType, Function::ExternalLinkage, method.name, module);
+    BasicBlock* bb = BasicBlock::Create(context, "entry", func);
+    
+    /*Function::arg_iterator args = func->arg_begin();
+
+    Argument* arg = &(*args);
+    
+    Value* val = llvm::ConstantFP::get(context, llvm::APFloat(5.0));
+    Value* val2 = llvm::ConstantFP::get(context, llvm::APFloat(1.0));
+    Value* result = builder.CreateFAdd(arg, val2, "add_constants");
+    builder.CreateRet(result);
+    */
+
+    pushBlock(bb);
+
+    IRBuilder<> builder(context);
+    builder.SetInsertPoint(bb);
+    for (auto& var : method.body->variables) {
+        llvm::AllocaInst* v = builder.CreateAlloca(Type::getDoubleTy(context));
+        var->allocaInst = v;
+    }
+    
+    for (auto& statement : method.body->statements) {
+        printf("statement visit\n");
+        statement->accept(statementVisitor, *this);
+    }
+    
+
+    
+    Value* val = llvm::ConstantFP::get(context, llvm::APFloat(5.0));
+    builder.CreateRet(val);
+
+    return func;
 }
-}
+
 
 

+ 36 - 6
src/CodeGeneration.h

@@ -2,17 +2,47 @@
 #define QLOW_CODE_GENERATION_H
 
 #include "Semantic.h"
+#include "CodegenVisitor.h"
+
+#include <stack>
+
 #include <llvm/IR/Module.h>
 
 namespace qlow
 {
-    namespace gen
-    {
-        std::unique_ptr<llvm::Module> generateModule(const sem::SymbolTable<sem::Class>& classes);
-        void generateObjectFile(const std::string& name, std::unique_ptr<llvm::Module> module);
-            
-    }
+namespace gen
+{
+    std::unique_ptr<llvm::Module> generateModule(const sem::SymbolTable<sem::Class>& classes);
+    void generateObjectFile(const std::string& name, std::unique_ptr<llvm::Module> module);
+
+    class FunctionGenerator;
 }
+}
+
+class qlow::gen::FunctionGenerator
+{
+const sem::Method& method;
+llvm::Module* module;
+
+std::stack<llvm::BasicBlock*> basicBlocks;
+
+public:
+
+StatementVisitor statementVisitor;
+ExpressionVisitor expressionVisitor;
+
+inline FunctionGenerator(const sem::Method& m, llvm::Module* module) :
+    method{ m }, module{ module }
+{
+}
+
+llvm::Function* generate(void);
+
+inline llvm::LLVMContext& getContext(void) const { return module->getContext(); }
+inline llvm::BasicBlock* getCurrentBlock(void) const { return basicBlocks.top(); }
+inline void pushBlock(llvm::BasicBlock* bb) { basicBlocks.push(bb); }
+inline llvm::BasicBlock* popBlock(void) { auto* bb = basicBlocks.top(); basicBlocks.pop(); return bb; }
+};
 
 
 #endif // QLOW_CODE_GENERATION_H

+ 44 - 4
src/CodegenVisitor.cpp

@@ -1,4 +1,5 @@
 #include "CodegenVisitor.h"
+#include "CodeGeneration.h"
 
 #include <llvm/IR/Constants.h>
 #include <llvm/IR/IRBuilder.h>
@@ -6,7 +7,7 @@
 
 using namespace qlow;
 
-llvm::Value* CodegenVisitor::visit(sem::BinaryOperation& binop, llvm::IRBuilder<>& builder)
+llvm::Value* ExpressionVisitor::visit(sem::BinaryOperation& binop, llvm::IRBuilder<>& builder)
 {
     using llvm::Value;
     Value* left = binop.left->accept(*this, builder);
@@ -24,18 +25,57 @@ llvm::Value* CodegenVisitor::visit(sem::BinaryOperation& binop, llvm::IRBuilder<
 }
 
 
-llvm::Value* CodegenVisitor::visit(sem::UnaryOperation& unop, llvm::IRBuilder<>& builder)
+llvm::Value* ExpressionVisitor::visit(sem::UnaryOperation& unop, llvm::IRBuilder<>& builder)
 {
     using llvm::Value;
+    Value* value = unop.arg->accept(*this, builder);
+
+    switch (unop.op) {
+        case ast::Operation::Operator::MINUS:
+            return builder.CreateNeg(value, "negate");
+
+        case ast::Operation::Operator::PLUS:
+        [[fallthrough]]
+        case ast::Operation::Operator::ASTERISK:
+        [[fallthrough]]
+        case ast::Operation::Operator::SLASH:
+            throw "operator not supported";
+    }
 }
 
-llvm::Value* CodegenVisitor::visit(sem::FeatureCallExpression& binop, llvm::IRBuilder<>& builder)
+llvm::Value* ExpressionVisitor::visit(sem::FeatureCallExpression& call, llvm::IRBuilder<>& builder)
 {
     using llvm::Value;
+    std::vector<Value*> arguments;
+    for (auto& arg : call.arguments) {
+        arguments.push_back(arg->accept(*this, builder));
+    }
+    //return builder.CreateCall(nullptr, arguments);
+    return nullptr;
 }
 
-llvm::Value* CodegenVisitor::visit(sem::IntConst& node, llvm::IRBuilder<>& builder)
+llvm::Value* ExpressionVisitor::visit(sem::IntConst& node, llvm::IRBuilder<>& builder)
 {
     return llvm::ConstantInt::get(builder.getContext(), llvm::APInt(32, std::to_string(node.value), 10));
 }
 
+
+llvm::Value* StatementVisitor::visit(sem::AssignmentStatement& assignment,
+        qlow::gen::FunctionGenerator& fg)
+{
+    llvm::IRBuilder<> builder(fg.getContext());
+    builder.SetInsertPoint(fg.getCurrentBlock());
+    llvm::Value* val = assignment.value->accept(fg.expressionVisitor, builder);
+    builder.CreateRet(val);
+    return llvm::ConstantFP::get(fg.getContext(), llvm::APFloat(5.0));
+}
+
+
+llvm::Value* StatementVisitor::visit(sem::FeatureCallStatement& assignment, gen::FunctionGenerator& fg)
+{
+    return llvm::ConstantFP::get(fg.getContext(), llvm::APFloat(5.0));
+}
+
+
+
+

+ 19 - 3
src/CodegenVisitor.h

@@ -3,6 +3,7 @@
 
 #include <llvm/IR/Value.h>
 #include <llvm/IR/IRBuilder.h>
+#include <llvm/IR/BasicBlock.h>
 
 #include "Visitor.h"
 #include "Semantic.h"
@@ -16,18 +17,19 @@ namespace qlow
 {
     namespace gen
     {
-        
+        class FunctionGenerator;        
     }
 }
 
 
 namespace qlow
 {
-    class CodegenVisitor;
+    class ExpressionVisitor;
+    class StatementVisitor;
 }
 
 
-class qlow::CodegenVisitor :
+class qlow::ExpressionVisitor :
     public Visitor<
         llvm::Value*,
         llvm::IRBuilder<>,
@@ -46,6 +48,20 @@ public:
 };
 
 
+class qlow::StatementVisitor :
+    public Visitor<
+        llvm::Value*,
+        gen::FunctionGenerator,
+
+        sem::AssignmentStatement,
+        sem::FeatureCallStatement
+    >
+{
+public:
+    llvm::Value* visit(sem::AssignmentStatement& node, gen::FunctionGenerator&) override;
+    llvm::Value* visit(sem::FeatureCallStatement& node, gen::FunctionGenerator&) override;
+};
+
 #endif // QLOW_CODEGEN_VISITOR_H
 
 

+ 10 - 7
src/Semantic.cpp

@@ -126,16 +126,19 @@ std::string Method::toString(void) const
 
 
 
-#define ACCEPT_DEFINITION(ClassName, Visitor) \
-llvm::Value* ClassName::accept(Visitor& v, llvm::IRBuilder<>& context) \
+#define ACCEPT_DEFINITION(ClassName, Visitor, Arg) \
+llvm::Value* ClassName::accept(Visitor& v, Arg arg) \
 { \
-    return v.visit(*this, context); \
+    return v.visit(*this, arg); \
 }
 
-ACCEPT_DEFINITION(BinaryOperation, CodegenVisitor)
-ACCEPT_DEFINITION(UnaryOperation, CodegenVisitor)
-ACCEPT_DEFINITION(FeatureCallExpression, CodegenVisitor)
-ACCEPT_DEFINITION(IntConst, CodegenVisitor)
+ACCEPT_DEFINITION(BinaryOperation, ExpressionVisitor, llvm::IRBuilder<>&)
+ACCEPT_DEFINITION(UnaryOperation, ExpressionVisitor, llvm::IRBuilder<>&)
+ACCEPT_DEFINITION(FeatureCallExpression, ExpressionVisitor, llvm::IRBuilder<>&)
+ACCEPT_DEFINITION(IntConst, ExpressionVisitor, llvm::IRBuilder<>&)
+
+ACCEPT_DEFINITION(AssignmentStatement, StatementVisitor, qlow::gen::FunctionGenerator&) 
+ACCEPT_DEFINITION(FeatureCallStatement, StatementVisitor, qlow::gen::FunctionGenerator&) 
 
 
 std::string SemanticException::getMessage(void) const

+ 23 - 8
src/Semantic.h

@@ -9,6 +9,7 @@
 
 #include <llvm/IR/Value.h>
 #include <llvm/IR/IRBuilder.h>
+#include <llvm/IR/BasicBlock.h>
 
 namespace qlow
 {
@@ -51,7 +52,12 @@ namespace qlow
         class SemanticException;
     }
     
-    class CodegenVisitor;
+    class ExpressionVisitor;
+    class StatementVisitor;
+    namespace gen
+    {
+        class FunctionGenerator;
+    }
 }
 
 
@@ -93,10 +99,14 @@ struct qlow::sem::Variable : public SemanticObject
 {
     Class* type;
     std::string name;
+
+    /// if this is a local variable, this stores a reference to the llvm
+    /// instance of this variable.
+    llvm::AllocaInst* allocaInst;
     
     Variable(void) = default;
     inline Variable(Class* type, std::string& name) :
-        type{ type }, name{ name } {}
+        type{ type }, name{ name }, allocaInst { nullptr } {}
 };
 
 
@@ -128,8 +138,9 @@ struct qlow::sem::DoEndBlock : public SemanticObject
 };
 
 
-struct qlow::sem::Statement : public SemanticObject
+struct qlow::sem::Statement : public SemanticObject, public Visitable<llvm::Value*, gen::FunctionGenerator, qlow::StatementVisitor>
 {
+    virtual llvm::Value* accept(qlow::StatementVisitor&, gen::FunctionGenerator&) = 0;
 };
 
 
@@ -137,10 +148,12 @@ struct qlow::sem::AssignmentStatement : public Statement
 {
     std::unique_ptr<Expression> target;
     std::unique_ptr<Expression> value;
+
+    virtual llvm::Value* accept(qlow::StatementVisitor&, gen::FunctionGenerator&);
 };
 
 
-struct qlow::sem::Expression : public SemanticObject, public Visitable<llvm::Value*, llvm::IRBuilder<>, qlow::CodegenVisitor>
+struct qlow::sem::Expression : public SemanticObject, public Visitable<llvm::Value*, llvm::IRBuilder<>, qlow::ExpressionVisitor>
 {
 };
 
@@ -156,7 +169,7 @@ struct qlow::sem::BinaryOperation : public Operation
     std::unique_ptr<Expression> left;
     std::unique_ptr<Expression> right;
     
-    virtual llvm::Value* accept(CodegenVisitor& visitor, llvm::IRBuilder<>& arg2);
+    virtual llvm::Value* accept(ExpressionVisitor& visitor, llvm::IRBuilder<>& arg2);
 };
 
 
@@ -164,14 +177,14 @@ struct qlow::sem::UnaryOperation : public Operation
 {
     qlow::ast::UnaryOperation::Side side;
     std::unique_ptr<Expression> arg;
-    virtual llvm::Value* accept(CodegenVisitor& visitor, llvm::IRBuilder<>& arg2);
+    virtual llvm::Value* accept(ExpressionVisitor& visitor, llvm::IRBuilder<>& arg2);
 };
 
 struct qlow::sem::FeatureCallExpression : public Expression
 {
     Method* callee;
     OwningList<Expression> arguments;
-    virtual llvm::Value* accept(CodegenVisitor& visitor, llvm::IRBuilder<>& arg2);
+    virtual llvm::Value* accept(ExpressionVisitor& visitor, llvm::IRBuilder<>& arg2);
 };
 
 
@@ -184,7 +197,7 @@ struct qlow::sem::IntConst : public Expression
     {
     }
     
-    virtual llvm::Value* accept(CodegenVisitor& visitor, llvm::IRBuilder<>& arg2);
+    virtual llvm::Value* accept(ExpressionVisitor& visitor, llvm::IRBuilder<>& arg2);
 };
 
 
@@ -193,6 +206,8 @@ struct qlow::sem::FeatureCallStatement : public Statement
     std::unique_ptr<FeatureCallExpression> expr;
     inline FeatureCallStatement(std::unique_ptr<FeatureCallExpression> expr) :
         expr{ std::move(expr) } {}
+
+    virtual llvm::Value* accept(qlow::StatementVisitor&, gen::FunctionGenerator&);
 };
 
 

+ 14 - 3
src/test.qlw

@@ -3,13 +3,20 @@
 class Main
     foo: Main
 
+    wow: Integer do
+        var: Integer;
+        var := 5;
+    end
+
     fop: FF do
         var: Integer;
         var := 5;
         var := 102 + var * var;
-        gagagaga;
-        
-        hohohoh;
+        var := 102 + var * var;
+        var := 102 + var * var;
+        var := 102 + var * var;
+        var := 102 + var * var;
+        var := 102 + var * var;
     end
 
     main: Integer do
@@ -18,6 +25,10 @@ class Main
 end
 
 class FF
+    sum_func: Integer do
+        variable: Integer;
+        variable := sum_func;
+    end
 end
 
 class Fudi