Nicolas Winkler 6 роки тому
батько
коміт
84c8ed44dc

+ 58 - 53
src/CodegenVisitor.cpp

@@ -8,6 +8,7 @@
 
 #include <llvm/IR/Constants.h>
 #include <llvm/IR/IRBuilder.h>
+#include <llvm/Support/raw_os_ostream.h>
 
 
 using namespace qlow;
@@ -147,15 +148,15 @@ llvm::Value* ExpressionCodegenVisitor::visit(sem::MethodCallExpression& call, ll
     std::vector<Value*> arguments;
     
     if (call.target != nullptr) {
-        auto* target = call.target->accept(fg.lvalueVisitor, builder);
+        auto* target = call.target->accept(*this, builder);
 
 #ifdef DEBUGGING
         Printer::getInstance() << "creating 'this' argument";
 #endif
-        if (llvm::LoadInst* li = llvm::dyn_cast<llvm::LoadInst>(target); li) {
-            llvm::Value* ptr = builder.CreateLoad(semCtxt.getLlvmType(call.target->type, builder.getContext())->getPointerTo(), li, "ptrload");
+        /*if (llvm::LoadInst* li = llvm::dyn_cast<llvm::LoadInst>(target); li) {
+            llvm::Value* ptr = builder.CreateLoad(semCtxt.getLlvmType(call.target->type, builder.getContext()), li, "ptrload");
             arguments.push_back(ptr);
-        } else
+        } else*/
             arguments.push_back(target);
     }
     
@@ -178,10 +179,12 @@ llvm::Value* ExpressionCodegenVisitor::visit(sem::MethodCallExpression& call, ll
 
 llvm::Value* ExpressionCodegenVisitor::visit(sem::FieldAccessExpression& access, llvm::IRBuilder<>& builder)
 {
-    /*using llvm::Value;
+    using llvm::Value;
     using llvm::Type;
+
+    sem::Context& semCtxt = access.context;
     
-    Type* type = access.target->type->getLlvmType(builder.getContext());
+    Type* type = semCtxt.getLlvmType(access.target->type, builder.getContext());
     
     if (type == nullptr)
         throw "no access type";
@@ -189,13 +192,18 @@ llvm::Value* ExpressionCodegenVisitor::visit(sem::FieldAccessExpression& access,
         type = type->getPointerElementType();
     }
     
-    llvm::Value* target = access.target->accept(fg.lvalueVisitor, builder);
-    
+    llvm::Value* target = access.target->accept(fg.lvalueVisitor, fg);
+    llvm::raw_os_ostream os(Printer::getInstance());
+    type->print(os);
+    os << "\n";
+    os.flush();
+
     int structIndex = access.accessed->llvmStructIndex;
     llvm::ArrayRef<Value*> indexList = {
         llvm::ConstantInt::get(builder.getContext(), llvm::APInt(32, structIndex, false)),
         llvm::ConstantInt::get(builder.getContext(), llvm::APInt(32, 0, false))
     };
+
     Value* ptr = builder.CreateGEP(type, target, indexList);
     return builder.CreateLoad(ptr);
     
@@ -204,15 +212,14 @@ llvm::Value* ExpressionCodegenVisitor::visit(sem::FieldAccessExpression& access,
     //                               llvm::ConstantInt::get(builder.getContext(),
     //                               llvm::APInt(32, 0, false)), 0);
     return llvm::ConstantInt::get(builder.getContext(),
-                                   llvm::APInt(32, 0, false));*/
-                                   return nullptr;
+                                   llvm::APInt(32, 0, false));
 }
 
 
 llvm::Value* ExpressionCodegenVisitor::visit(sem::AddressExpression& node, llvm::IRBuilder<>& builder)
 {
     using llvm::Value;
-    Value* lvalue = node.target->accept(fg.lvalueVisitor, builder);
+    Value* lvalue = node.target->accept(fg.lvalueVisitor, fg);
     
     // this check is unnecessary
     if (auto* allocaInst = llvm::dyn_cast<llvm::AllocaInst>(lvalue)) {
@@ -237,13 +244,13 @@ llvm::Value* ExpressionCodegenVisitor::visit(sem::ThisExpression& thisExpr, llvm
 }
 
 
-llvm::Value* LValueVisitor::visit(sem::Expression& e, llvm::IRBuilder<>& builder)
+llvm::Value* LValueVisitor::visit(sem::Expression& e, qlow::gen::FunctionGenerator& fg)
 {
     throw "cannot construct lvalue from expression";
 }
 
 
-llvm::Value* LValueVisitor::visit(sem::LocalVariableExpression& lve, llvm::IRBuilder<>& builder)
+llvm::Value* LValueVisitor::visit(sem::LocalVariableExpression& lve, qlow::gen::FunctionGenerator& fg)
 {
     assert(lve.var->allocaInst != nullptr);
     
@@ -260,12 +267,13 @@ llvm::Value* LValueVisitor::visit(sem::LocalVariableExpression& lve, llvm::IRBui
         return lve.var->allocaInst;
     }
     else {
-        throw "unable to find alloca instance of local variable";
+        return lve.var->allocaInst;
+        //throw "unable to find alloca instance of local variable";
     }
 }
 
 
-llvm::Value* LValueVisitor::visit(sem::FieldAccessExpression& access, llvm::IRBuilder<>& builder)
+llvm::Value* LValueVisitor::visit(sem::FieldAccessExpression& access, qlow::gen::FunctionGenerator& fg)
 {
     /*
     using llvm::Value;
@@ -287,8 +295,9 @@ llvm::Value* LValueVisitor::visit(sem::FieldAccessExpression& access, llvm::IRBu
     
     using llvm::Value;
     using llvm::Type;
+    sem::Context& semCtxt = access.context;
     
-    /*Type* type = access.target->type->getLlvmType(builder.getContext());
+    Type* type = semCtxt.getLlvmType(access.target->type, fg.builder.getContext());
     
     if (type == nullptr)
         throw "no access type";
@@ -296,16 +305,15 @@ llvm::Value* LValueVisitor::visit(sem::FieldAccessExpression& access, llvm::IRBu
         type = type->getPointerElementType();
     }
     
-    llvm::Value* target = access.target->accept(*this, builder);
+    llvm::Value* target = access.target->accept(fg.expressionVisitor, fg.builder);
     
     int structIndex = access.accessed->llvmStructIndex;
     llvm::ArrayRef<Value*> indexList = {
-        llvm::ConstantInt::get(builder.getContext(), llvm::APInt(32, structIndex, false)),
-        llvm::ConstantInt::get(builder.getContext(), llvm::APInt(32, 0, false))
+        llvm::ConstantInt::get(fg.builder.getContext(), llvm::APInt(32, structIndex, false)),
+        llvm::ConstantInt::get(fg.builder.getContext(), llvm::APInt(32, 0, false))
     };
-    Value* ptr = builder.CreateGEP(type, target, indexList);
-    return ptr;*/
-    return nullptr;
+    Value* ptr = fg.builder.CreateGEP(type, target, indexList);
+    return ptr;
 }
 
 
@@ -325,9 +333,9 @@ llvm::Value* StatementVisitor::visit(sem::IfElseBlock& ifElseBlock,
     using llvm::Value;
     using llvm::BasicBlock;
     
-    llvm::IRBuilder<> builder(fg.getContext());
-    builder.SetInsertPoint(fg.getCurrentBlock());
-    auto condition = ifElseBlock.condition->accept(fg.expressionVisitor, builder);
+
+    fg.builder.SetInsertPoint(fg.getCurrentBlock());
+    auto condition = ifElseBlock.condition->accept(fg.expressionVisitor, fg.builder);
     
     llvm::Function* function = fg.getCurrentBlock()->getParent();
     
@@ -335,21 +343,21 @@ llvm::Value* StatementVisitor::visit(sem::IfElseBlock& ifElseBlock,
     BasicBlock* elseB = BasicBlock::Create(fg.getContext(), "else", function);
     BasicBlock* merge = BasicBlock::Create(fg.getContext(), "merge", function);
     
-    Value* boolCond = builder.CreateIntCast(condition, llvm::Type::getInt1Ty(fg.getContext()), false);
+    Value* boolCond = fg.builder.CreateIntCast(condition, llvm::Type::getInt1Ty(fg.getContext()), false);
     
-    builder.CreateCondBr(boolCond, thenB, elseB);  
+    fg.builder.CreateCondBr(boolCond, thenB, elseB);  
     
     fg.pushBlock(thenB);
     ifElseBlock.ifBlock->accept(*this, fg);
-    builder.SetInsertPoint(thenB);
+    fg.builder.SetInsertPoint(thenB);
     if (!thenB->getTerminator())
-        builder.CreateBr(merge);
+        fg.builder.CreateBr(merge);
     fg.popBlock();
     fg.pushBlock(elseB);
     ifElseBlock.elseBlock->accept(*this, fg);
-    builder.SetInsertPoint(elseB);
+    fg.builder.SetInsertPoint(elseB);
     if (!elseB->getTerminator())
-        builder.CreateBr(merge);
+        fg.builder.CreateBr(merge);
     fg.popBlock();
     fg.popBlock();
     fg.pushBlock(merge);
@@ -363,8 +371,7 @@ llvm::Value* StatementVisitor::visit(sem::WhileBlock& whileBlock,
     using llvm::Value;
     using llvm::BasicBlock;
     
-    llvm::IRBuilder<> builder(fg.getContext());
-    builder.SetInsertPoint(fg.getCurrentBlock());
+    fg.builder.SetInsertPoint(fg.getCurrentBlock());
     
     llvm::Function* function = fg.getCurrentBlock()->getParent();
     
@@ -374,18 +381,18 @@ llvm::Value* StatementVisitor::visit(sem::WhileBlock& whileBlock,
     
     
     //builder.CreateCondBr(boolCond, body, merge);
-    builder.CreateBr(startloop);
+    fg.builder.CreateBr(startloop);
     fg.pushBlock(startloop);
-    builder.SetInsertPoint(startloop);
-    auto condition = whileBlock.condition->accept(fg.expressionVisitor, builder);
-    Value* boolCond = builder.CreateIntCast(condition, llvm::Type::getInt1Ty(fg.getContext()), false);
-    builder.CreateCondBr(condition, body, merge);
+    fg.builder.SetInsertPoint(startloop);
+    auto condition = whileBlock.condition->accept(fg.expressionVisitor, fg.builder);
+    Value* boolCond = fg.builder.CreateIntCast(condition, llvm::Type::getInt1Ty(fg.getContext()), false);
+    fg.builder.CreateCondBr(condition, body, merge);
     fg.popBlock();
     
     fg.pushBlock(body);
     whileBlock.body->accept(*this, fg);
-    builder.SetInsertPoint(body);
-    builder.CreateBr(startloop);
+    fg.builder.SetInsertPoint(body);
+    fg.builder.CreateBr(startloop);
     fg.popBlock();
     fg.pushBlock(merge);
     return nullptr;
@@ -396,14 +403,14 @@ llvm::Value* StatementVisitor::visit(sem::AssignmentStatement& assignment,
         qlow::gen::FunctionGenerator& fg)
 {
     Printer& printer = Printer::getInstance();
-    llvm::IRBuilder<> builder(fg.getContext());
-    builder.SetInsertPoint(fg.getCurrentBlock());
+    fg.builder.SetInsertPoint(fg.getCurrentBlock());
     
-    auto val = assignment.value->accept(fg.expressionVisitor, builder);
-    auto target = assignment.target->accept(fg.lvalueVisitor, builder);
+    auto val = assignment.value->accept(fg.expressionVisitor, fg.builder);
+    auto target = assignment.target->accept(fg.lvalueVisitor, fg);
     
-    return builder.CreateStore(val, target);
+    return fg.builder.CreateStore(val, target);
     
+    /*
     if (auto* targetVar =
         dynamic_cast<sem::LocalVariableExpression*>(assignment.target.get()); targetVar) {
 #ifdef DEBUGGING
@@ -437,17 +444,16 @@ llvm::Value* StatementVisitor::visit(sem::AssignmentStatement& assignment,
     }
     
     return nullptr;
-    //return llvm::ConstantFP::get(fg.getContext(), llvm::APFloat(5123.0));
+    //return llvm::ConstantFP::get(fg.getContext(), llvm::APFloat(5123.0));*/
 }
 
 
 llvm::Value* StatementVisitor::visit(sem::ReturnStatement& returnStatement,
         qlow::gen::FunctionGenerator& fg)
 {
-    llvm::IRBuilder<> builder(fg.getContext());
-    builder.SetInsertPoint(fg.getCurrentBlock());
-    auto val = returnStatement.value->accept(fg.expressionVisitor, builder);
-    builder.CreateRet(val);
+    fg.builder.SetInsertPoint(fg.getCurrentBlock());
+    auto val = returnStatement.value->accept(fg.expressionVisitor, fg.builder);
+    fg.builder.CreateRet(val);
     return val;
 }
 
@@ -455,11 +461,10 @@ llvm::Value* StatementVisitor::visit(sem::ReturnStatement& returnStatement,
 llvm::Value* StatementVisitor::visit(sem::FeatureCallStatement& fc, gen::FunctionGenerator& fg)
 {
     llvm::Module* module = fg.getModule();
-    llvm::IRBuilder<> builder(fg.getContext());
-    builder.SetInsertPoint(fg.getCurrentBlock());
+    fg.builder.SetInsertPoint(fg.getCurrentBlock());
     //llvm::Constant* c = module->getOrInsertFunction(fc.expr->callee->name, {});
     
-    return fc.expr->accept(fg.expressionVisitor, builder);
+    return fc.expr->accept(fg.expressionVisitor, fg.builder);
     
     /*
     llvm::Function* f = fc.expr->callee->llvmNode;

+ 4 - 4
src/CodegenVisitor.h

@@ -73,7 +73,7 @@ public:
 class qlow::LValueVisitor :
     public Visitor<
         llvm::Value*,
-        llvm::IRBuilder<>,
+        qlow::gen::FunctionGenerator,
 
         sem::Expression,
         sem::LocalVariableExpression,
@@ -81,9 +81,9 @@ class qlow::LValueVisitor :
     >
 {
 public:
-    llvm::Value* visit(sem::Expression& node, llvm::IRBuilder<>&) override;
-    llvm::Value* visit(sem::LocalVariableExpression& node, llvm::IRBuilder<>&) override;
-    llvm::Value* visit(sem::FieldAccessExpression& node, llvm::IRBuilder<>&) override;
+    llvm::Value* visit(sem::Expression& node, qlow::gen::FunctionGenerator& fg) override;
+    llvm::Value* visit(sem::LocalVariableExpression& node, qlow::gen::FunctionGenerator& fg) override;
+    llvm::Value* visit(sem::FieldAccessExpression& node, qlow::gen::FunctionGenerator& fg) override;
 };
 
 

+ 17 - 4
src/ErrorReporting.cpp

@@ -81,6 +81,8 @@ void InternalError::print(Printer& printer) const noexcept
 
 const std::string& InternalError::getMessage(void) const noexcept
 {
+    using namespace std::literals;
+
     static std::map<ErrorCode, std::string> errors = {
         {ErrorCode::OUT_OF_MEMORY, "out of memory"},
         {ErrorCode::PARSER_INIT_FAILED, "parser initialization failed"},
@@ -88,7 +90,13 @@ const std::string& InternalError::getMessage(void) const noexcept
         {ErrorCode::PARSER_FAILED, "parser failed"},
         {ErrorCode::PARSER_FAILED, "invalid type encountered"},
     };
-    return errors.at(errorCode);
+
+    if (errors.find(errorCode) != errors.end())
+        return errors.at(errorCode);
+    else {
+        static std::string msg = "error message not found"s;
+        return msg;
+    }
 }
 
 
@@ -201,7 +209,8 @@ void SemanticError::print(Printer& printer) const noexcept
 
 std::string SemanticError::getMessage(void) const noexcept
 {
-    static const std::map<ErrorCode, std::string> error = {
+    using namespace std::literals;
+    static const std::map<ErrorCode, std::string> errors = {
         {UNKNOWN_TYPE, "unknown type"},
         {FEATURE_NOT_FOUND, "method or variable not found"},
         {DUPLICATE_CLASS_DEFINITION, "duplicate class definition"},
@@ -209,15 +218,19 @@ std::string SemanticError::getMessage(void) const noexcept
         {DUPLICATE_METHOD_DEFINITION, "duplicate method definition"},
         {OPERATOR_NOT_FOUND, ""},
         {WRONG_NUMBER_OF_ARGUMENTS, "wrong number of arguments passed"},
+        {INVALID_RETURN_TYPE, "invalid return type"},
     };
-    return error.at(errorCode);
+    if (errors.find(errorCode) != errors.end())
+        return errors.at(errorCode);
+    else
+        return "error message not found"s;
 }
 
 
 SemanticError SemanticError::invalidReturnType(const std::string& should,
     const std::string& is, const CodePosition& where)
 {
-    return SemanticError{ INVALID_RETURN_TYPE, "invalid return type: return type should be " +
+    return SemanticError{ INVALID_RETURN_TYPE, "return type should be " +
         should + ", but " + is + " is given.", where };
 }
 

+ 2 - 2
src/main.cpp

@@ -13,10 +13,10 @@
 
 int main(int argc, char** argv) try
 {
-    std::set_terminate ([] () {
+    /*std::set_terminate ([] () {
         qlow::printError(qlow::Printer::getInstance(), "severe internal compiler error");
         exit(1);
-    });
+    });*/
 
     qlow::Driver driver(argc, argv);
     return driver.run();

+ 6 - 4
src/sem/CodeGeneration.cpp

@@ -115,7 +115,7 @@ std::unique_ptr<llvm::Module> generateModule(sem::GlobalScope& semantic)
 #ifdef DEBUGGING
                 module->print(verifyStream, nullptr);
 #endif
-                throw "corrupt llvm function";
+                throw (std::string("corrupt llvm function") + method->name).c_str();
             }
 #ifdef DEBUGGING
             printf("verified function: %s\n", method->name.c_str());
@@ -132,7 +132,7 @@ std::unique_ptr<llvm::Module> generateModule(sem::GlobalScope& semantic)
         bool corrupt = llvm::verifyFunction(*f, &verifyStream);
         if (corrupt) {
             module->print(verifyStream, nullptr);
-            throw "corrupt llvm function";
+            throw method->name.c_str();
         }
 #ifdef DEBUGGING
         printf("verified function: %s\n", method->name.c_str());
@@ -273,7 +273,7 @@ void generateObjectFile(const std::string& filename, std::unique_ptr<llvm::Modul
 #endif
     targetMachine->addPassesToEmitFile(pm, dest,
 //        llvm::LLVMTargetMachine::CGFT_ObjectFile,
-        nullptr,
+//        nullptr,
         llvm::TargetMachine::CGFT_ObjectFile);
 
     pm.run(*module);
@@ -342,7 +342,9 @@ llvm::Function* qlow::gen::FunctionGenerator::generate(void)
     
     builder.SetInsertPoint(getCurrentBlock());
     //if (method.returnType->equals(sem::NativeType(sem::NativeType::Type::VOID))) {
-    if (method.returnType == sem::NO_TYPE) {
+    if (method.returnType == sem::NO_TYPE ||
+        (semCtxt.getType(method.returnType).getKind() == sem::Type::Kind::NATIVE &&
+        semCtxt.getType(method.returnType).getNativeKind() == sem::Type::Native::VOID)) {
         if (!getCurrentBlock()->getTerminator())
             builder.CreateRetVoid();
     }

+ 4 - 1
src/sem/CodeGeneration.h

@@ -8,6 +8,7 @@
 #include <stack>
 
 #include <llvm/IR/Module.h>
+#include <llvm/IR/IRBuilder.h>
 
 namespace qlow
 {
@@ -34,13 +35,15 @@ public:
     StatementVisitor statementVisitor;
     ExpressionCodegenVisitor expressionVisitor;
     LValueVisitor lvalueVisitor;
+    llvm::IRBuilder<> builder;
 
     inline FunctionGenerator(const sem::Method& m, llvm::Module* module,
         llvm::AttributeSet& attributes) :
         method{ m },
         module{ module },
         attributes{ attributes },
-        expressionVisitor{ *this }
+        expressionVisitor{ *this },
+        builder{ module->getContext() }
     {
     }
 

+ 6 - 3
src/sem/Context.cpp

@@ -21,13 +21,15 @@ Context::Context(void)
 
 
 qlow::sem::TypeId Context::addType(Type&& type) {
-    if (typesMap.find(type) != typesMap.end()) {
+    if (typesMap.count(type) != 0) {
         return typesMap[type];
     }
     else {
         Type gogo = std::move(type);
         types.push_back({ std::move(gogo), nullptr });
-        return types.size() - 1;
+        auto id = types.size() - 1;
+        typesMap[types[id].first] = id;
+        return id;
     }
 }
 
@@ -126,7 +128,7 @@ void Context::createLlvmTypes(llvm::LLVMContext& llvmCtxt)
 {
     for (auto& [type, llvmType] : types) {
         if (type.getKind() != Type::Kind::NATIVE) {
-            llvmType = llvm::StructType::create(llvmCtxt);
+            llvmType = llvm::StructType::create(llvmCtxt, type.asIdentifier());
         }
     }
     for (auto& [type, llvmType] : types) {
@@ -154,6 +156,7 @@ void Context::createLlvmTypes(llvm::LLVMContext& llvmCtxt)
             }
 
             llvm::dyn_cast<llvm::StructType>(llvmType)->setBody(llvm::ArrayRef(structTypes));
+            llvmType = llvmType->getPointerTo();
         }
     }
 }

+ 11 - 1
src/sem/Context.h

@@ -27,6 +27,16 @@ namespace std
     {
         size_t operator() (const std::reference_wrapper<qlow::sem::Type>& t) const;
     };
+
+
+    template<>
+    struct equal_to<std::reference_wrapper<qlow::sem::Type>>
+    {
+        inline bool operator() (const std::reference_wrapper<qlow::sem::Type>& a, const std::reference_wrapper<qlow::sem::Type>& b) const
+        {
+            return a.get() == b.get();
+        }
+    };
 }
 
 
@@ -34,7 +44,7 @@ class qlow::sem::Context
 {
 private:
     std::vector<std::pair<Type, llvm::Type*>> types;
-    std::unordered_map<std::reference_wrapper<Type>, TypeId, std::hash<std::reference_wrapper<Type>>, std::equal_to<Type>> typesMap;
+    std::unordered_map<std::reference_wrapper<Type>, TypeId> typesMap;
 
     std::unique_ptr<NativeScope> nativeScope;
 public:

+ 3 - 3
src/sem/Semantic.cpp

@@ -184,9 +184,9 @@ ACCEPT_DEFINITION(AddressExpression, ExpressionCodegenVisitor, llvm::Value*, llv
 ACCEPT_DEFINITION(IntConst, ExpressionCodegenVisitor, llvm::Value*, llvm::IRBuilder<>&)
 ACCEPT_DEFINITION(ThisExpression, ExpressionCodegenVisitor, llvm::Value*, llvm::IRBuilder<>&)
 
-ACCEPT_DEFINITION(Expression, LValueVisitor, llvm::Value*, llvm::IRBuilder<>&)
-ACCEPT_DEFINITION(LocalVariableExpression, LValueVisitor, llvm::Value*, llvm::IRBuilder<>&)
-ACCEPT_DEFINITION(FieldAccessExpression, LValueVisitor, llvm::Value*, llvm::IRBuilder<>&)
+ACCEPT_DEFINITION(Expression, LValueVisitor, llvm::Value*, qlow::gen::FunctionGenerator&)
+ACCEPT_DEFINITION(LocalVariableExpression, LValueVisitor, llvm::Value*, qlow::gen::FunctionGenerator&)
+ACCEPT_DEFINITION(FieldAccessExpression, LValueVisitor, llvm::Value*, qlow::gen::FunctionGenerator&)
 
 ACCEPT_DEFINITION(AssignmentStatement, StatementVisitor, llvm::Value*, qlow::gen::FunctionGenerator&) 
 ACCEPT_DEFINITION(DoEndBlock, StatementVisitor, llvm::Value*, qlow::gen::FunctionGenerator&) 

+ 4 - 4
src/sem/Semantic.h

@@ -288,7 +288,7 @@ struct qlow::sem::Expression :
                      llvm::IRBuilder<>,
                      qlow::ExpressionCodegenVisitor>,
     public Visitable<llvm::Value*,
-                     llvm::IRBuilder<>,
+                     qlow::gen::FunctionGenerator,
                      qlow::LValueVisitor>
 {
     TypeId type;
@@ -302,7 +302,7 @@ struct qlow::sem::Expression :
     inline virtual bool isLValue(void) const { return false; }
     
     virtual llvm::Value* accept(ExpressionCodegenVisitor& visitor, llvm::IRBuilder<>& arg2) override = 0;
-    virtual llvm::Value* accept(LValueVisitor& visitor, llvm::IRBuilder<>& arg2) override;
+    virtual llvm::Value* accept(LValueVisitor& visitor, qlow::gen::FunctionGenerator&) override;
 };
 
 
@@ -330,7 +330,7 @@ struct qlow::sem::LocalVariableExpression : public Expression
     inline virtual bool isLValue(void) const override { return true; }
 
     virtual llvm::Value* accept(ExpressionCodegenVisitor& visitor, llvm::IRBuilder<>& arg2) override;
-    virtual llvm::Value* accept(LValueVisitor& visitor, llvm::IRBuilder<>& arg2) override;
+    virtual llvm::Value* accept(LValueVisitor& visitor, qlow::gen::FunctionGenerator&) override;
     virtual std::string toString(void) const override;
 };
 
@@ -462,7 +462,7 @@ struct qlow::sem::FieldAccessExpression : public Expression
     inline virtual bool isLValue(void) const override { return true; }
     
     virtual llvm::Value* accept(ExpressionCodegenVisitor& visitor, llvm::IRBuilder<>& arg2) override;
-    virtual llvm::Value* accept(LValueVisitor& visitor, llvm::IRBuilder<>& arg2) override;
+    virtual llvm::Value* accept(LValueVisitor& visitor, qlow::gen::FunctionGenerator&) override;
     
     virtual std::string toString(void) const override;
 };

+ 26 - 1
src/sem/Type.cpp

@@ -82,6 +82,31 @@ std::string Type::asString(void) const
 }
 
 
+std::string Type::asIdentifier(void) const
+{
+    using namespace std::literals;
+    return std::visit(
+        [&] (const auto& t) -> std::string {
+            using T = std::decay_t<decltype(t)>;
+            if constexpr (std::is_same<T, NativeType>::value) {
+                return "native";
+            }
+            else if constexpr (std::is_same<T, ClassType>::value) {
+                return this->getClass()->name;
+            }
+            else if constexpr (std::is_same<T, PointerType>::value) {
+                return this->typeScope->getContext().getType(t.targetType).asIdentifier() + "_ptr";
+            }
+            else if constexpr (std::is_same<T, ArrayType>::value) {
+                return this->typeScope->getContext().getType(t.targetType).asIdentifier() + "_arr";
+            }
+        }
+        ,
+        type
+    );
+}
+
+
 size_t Type::hash(void) const
 {
     auto value1 = std::visit(
@@ -103,7 +128,7 @@ size_t Type::hash(void) const
         },
         type
     );
-    auto h = type.index() * 11111111111111111 + value1;
+    auto h = type.index() * 2542345234523 + value1;
     Printer::getInstance() << h << std::endl;
     return h;
 }

+ 2 - 0
src/sem/Type.h

@@ -106,9 +106,11 @@ public:
     Native getNativeKind(void) const;
 
     std::string asString(void) const;
+    std::string asIdentifier(void) const;
     size_t hash(void) const;
 
     bool operator == (const Type& other) const;
+    inline bool operator != (const Type& other) const { return !this->operator==(other); }
 
     /**
      * @brief return the class of this type if it is a class type,