Ver Fonte

workin on structs

Nicolas Winkler há 6 anos atrás
pai
commit
d410cd6239

+ 2 - 2
src/Builtin.cpp

@@ -237,9 +237,9 @@ llvm::Value* qlow::sem::BinaryNativeMethod::generateCode(llvm::IRBuilder<>& buil
     Printer& p = Printer::getInstance();
     llvm::raw_os_ostream pp(p);
     p << "creating native binop with llvm-types ";
-    arguments[0]->getType()->print(pp); pp.flush();
+    arguments[0]->getType()->print(pp, true); pp.flush();
     p << ", ";
-    arguments[1]->getType()->print(pp); pp.flush();
+    arguments[1]->getType()->print(pp, true); pp.flush();
     p << std::endl;
 #endif
     return generator(builder, arguments[0], arguments[1]);

+ 13 - 8
src/CodegenVisitor.cpp

@@ -16,7 +16,8 @@ llvm::Value* ExpressionCodegenVisitor::visit(sem::LocalVariableExpression& lve,
 {
     assert(lve.var->allocaInst != nullptr);
     if (llvm::dyn_cast<llvm::AllocaInst>(lve.var->allocaInst)) {
-        llvm::Value* val = builder.CreateLoad(lve.var->allocaInst);
+        llvm::Type* returnType = lve.context.getLlvmType(lve.type, builder.getContext());
+        llvm::Value* val = builder.CreateLoad(returnType, lve.var->allocaInst);
         return val;
     }
     else {
@@ -135,7 +136,10 @@ llvm::Value* ExpressionCodegenVisitor::visit(sem::NewArrayExpression& naexpr, ll
 
 llvm::Value* ExpressionCodegenVisitor::visit(sem::MethodCallExpression& call, llvm::IRBuilder<>& builder)
 {
-    /*using llvm::Value;
+    using llvm::Value;
+
+    sem::Context& semCtxt = call.context;
+
     if (call.arguments.size() != call.callee->arguments.size()) {
         throw "wrong number of arguments";
     }
@@ -144,10 +148,12 @@ llvm::Value* ExpressionCodegenVisitor::visit(sem::MethodCallExpression& call, ll
     
     if (call.target != nullptr) {
         auto* target = call.target->accept(fg.lvalueVisitor, builder);
-        
-        Printer::getInstance().debug() << "creating 'this' argument";
+
+#ifdef DEBUGGING
+        Printer::getInstance() << "creating 'this' argument";
+#endif
         if (llvm::LoadInst* li = llvm::dyn_cast<llvm::LoadInst>(target); li) {
-            llvm::Value* ptr = builder.CreateLoad(call.target->type->getLlvmType(builder.getContext())->getPointerTo(), li, "ptrload");
+            llvm::Value* ptr = builder.CreateLoad(semCtxt.getLlvmType(call.target->type, builder.getContext())->getPointerTo(), li, "ptrload");
             arguments.push_back(ptr);
         } else
             arguments.push_back(target);
@@ -158,7 +164,7 @@ llvm::Value* ExpressionCodegenVisitor::visit(sem::MethodCallExpression& call, ll
         auto& arg = call.arguments[i];
         auto value = arg->accept(*this, builder);
         
-        if (!arg->type->equals(*call.callee->arguments[i]->type.get())) {
+        if (arg->type != call.callee->arguments[i]->type) {
             throw "argument type mismatch";
         }
         
@@ -166,8 +172,7 @@ llvm::Value* ExpressionCodegenVisitor::visit(sem::MethodCallExpression& call, ll
     }
     //auto returnType = call.callee->returnType;
     llvm::CallInst* callInst = builder.CreateCall(call.callee->llvmNode, arguments);
-    return callInst;*/
-    return nullptr;
+    return callInst;
 }
 
 

+ 1 - 1
src/Scope.cpp

@@ -61,7 +61,7 @@ sem::TypeId sem::GlobalScope::getType(const ast::Type* name)
     }
     
     auto native = context.getNativeScope().getType(name);
-    if (native) {
+    if (native != sem::NO_TYPE) {
         return native;
     }
 

+ 3 - 0
src/ast/Ast.h

@@ -146,6 +146,9 @@ struct qlow::ast::Type : public AstObject
 };
 
 
+///
+/// \brief represents a type identified by a single identifier
+///
 struct qlow::ast::ClassType : public ast::Type
 {
     std::string typeName;

+ 4 - 4
src/ast/AstVisitor.cpp

@@ -64,7 +64,7 @@ std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::MethodDefiniti
                 unique_dynamic_cast<sem::Variable>(std::move(var));
             variable->isParameter = true;
             m->arguments.push_back(variable.get());
-            std::string varname = variable->name;
+            std::string& varname = variable->name;
             m->scope.putVariable(varname, std::move(variable));
         }
         else {
@@ -118,7 +118,7 @@ std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::DoEndBlock& as
                 throw SemanticError(SemanticError::UNKNOWN_TYPE,
                                     nvs->type->asString(),
                                     nvs->type->pos);
-            auto var = std::make_unique<sem::Variable>(scope.getContext(), std::move(type), nvs->name);
+            auto var = std::make_unique<sem::Variable>(scope.getContext(), type, nvs->name);
             body->scope.putVariable(nvs->name, std::move(var));
             continue;
         }
@@ -384,12 +384,12 @@ std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::BinaryOperatio
 
     auto& leftType = context.getType(leftEval->type);
     auto& rightType = context.getType(rightEval->type);
-    
+
     auto& scop =  leftType.getTypeScope();
     sem::Method* operationMethod = scop.resolveMethod(
         ast.opString, { rightEval->type }
     );
-    
+
 #ifdef DEBUGGING
     Printer::getInstance() << "looked for operation method for operator " <<
         ast.opString << std::endl;

+ 3 - 2
src/main.cpp

@@ -5,6 +5,7 @@
 
 #include "Ast.h"
 #include "Semantic.h"
+#include "ErrorReporting.h"
 #include "Builtin.h"
 #include "CodeGeneration.h"
 
@@ -13,8 +14,8 @@
 int main(int argc, char** argv) try
 {
     std::set_terminate ([] () {
-        std::cerr << "terminated" << std::endl;
-        abort();
+        qlow::printError(qlow::Printer::getInstance(), "severe internal compiler error");
+        exit(1);
     });
 
     qlow::Driver driver(argc, argv);

+ 10 - 7
src/sem/CodeGeneration.cpp

@@ -26,7 +26,7 @@ namespace qlow
 namespace gen
 {
 
-std::unique_ptr<llvm::Module> generateModule(const sem::GlobalScope& semantic)
+std::unique_ptr<llvm::Module> generateModule(sem::GlobalScope& semantic)
 {
     using llvm::Module;
     using llvm::Function;
@@ -47,6 +47,7 @@ std::unique_ptr<llvm::Module> generateModule(const sem::GlobalScope& semantic)
 
     // create llvm structs
     // TODO implement detection of circles
+    /*
     for (const auto& [name, cl] : semantic.getClasses()) {
         llvm::StructType* st;
         std::vector<llvm::Type*> fields;
@@ -63,10 +64,11 @@ std::unique_ptr<llvm::Module> generateModule(const sem::GlobalScope& semantic)
                 throw "internal error: possible circular dependency";
             
             llvmStructIndex++;
-        }*/
+        }*//*
         st = llvm::StructType::create(context, fields, name);
         cl->llvmType = st;
-    }
+    }*/
+    semantic.getContext().createLlvmTypes(context);
     
     llvm::AttrBuilder ab;
     ab.addAttribute(llvm::Attribute::AttrKind::NoInline);
@@ -261,16 +263,17 @@ void generateObjectFile(const std::string& filename, std::unique_ptr<llvm::Modul
 
     TargetOptions targetOptions;
     auto relocModel = llvm::Optional<llvm::Reloc::Model>(llvm::Reloc::Model::PIC_);
-    std::unique_ptr<TargetMachine> targetMachine(
-        target->createTargetMachine(targetTriple, cpu,
-            features, targetOptions, relocModel));
+    TargetMachine* targetMachine = target->createTargetMachine(targetTriple, cpu,
+            features, targetOptions, relocModel);
 
     std::error_code errorCode;
     raw_fd_ostream dest(filename, errorCode, llvm::sys::fs::F_None);
+#ifdef DEBUGGING
     printer << "adding passes" << std::endl;
+#endif
     targetMachine->addPassesToEmitFile(pm, dest,
 //        llvm::LLVMTargetMachine::CGFT_ObjectFile,
-        nullptr,
+//        nullptr,
         llvm::TargetMachine::CGFT_ObjectFile);
 
     pm.run(*module);

+ 1 - 1
src/sem/CodeGeneration.h

@@ -13,7 +13,7 @@ namespace qlow
 {
 namespace gen
 {
-    std::unique_ptr<llvm::Module> generateModule(const sem::GlobalScope& objects);
+    std::unique_ptr<llvm::Module> generateModule(sem::GlobalScope& objects);
     llvm::Function* generateFunction (llvm::Module* module, sem::Method* method);
     void generateObjectFile(const std::string& name, std::unique_ptr<llvm::Module> module, int optLevel);
 

+ 37 - 6
src/sem/Context.cpp

@@ -114,12 +114,6 @@ llvm::Type* Context::getLlvmType(TypeId id, llvm::LLVMContext& llvmCtxt)
     // TODO at the moment, all types are integers --> fix that
     if (id < types.size()) {
         auto& llt = types[id].second;
-        if (llt == nullptr) {
-            if (id == 0)
-                llt = llvm::Type::getInt1Ty(llvmCtxt);
-            else
-                llt = llvm::Type::getInt64Ty(llvmCtxt);
-        }
         return llt;
     }
     else {
@@ -127,3 +121,40 @@ llvm::Type* Context::getLlvmType(TypeId id, llvm::LLVMContext& llvmCtxt)
     }
 }
 
+
+void Context::createLlvmTypes(llvm::LLVMContext& llvmCtxt)
+{
+    for (auto& [type, llvmType] : types) {
+        if (type.getKind() != Type::Kind::NATIVE) {
+            llvmType = llvm::StructType::create(llvmCtxt);
+        }
+    }
+    for (auto& [type, llvmType] : types) {
+        if (type.getKind() == Type::Kind::NATIVE) {
+            switch (type.getNativeKind()) {
+            case Type::Native::BOOLEAN:
+                llvmType = llvm::Type::getInt1Ty(llvmCtxt);
+                break;
+            case Type::Native::INTEGER:
+                llvmType = llvm::Type::getInt64Ty(llvmCtxt);
+                break;
+            case Type::Native::VOID:
+                llvmType = llvm::Type::getVoidTy(llvmCtxt);
+                break;
+            }
+        }
+    }
+    for (auto& [type, llvmType] : types) {
+        if (type.getKind() == Type::Kind::CLASS) {
+            std::vector<llvm::Type*> structTypes;
+
+            for (auto& [name, field] : type.getClass()->fields) {
+                structTypes.push_back(types[field->type].second);
+                field->llvmStructIndex = structTypes.size() - 1;
+            }
+
+            llvm::dyn_cast<llvm::StructType>(llvmType)->setBody(llvm::ArrayRef(structTypes));
+        }
+    }
+}
+

+ 2 - 0
src/sem/Context.h

@@ -62,6 +62,8 @@ public:
     TypeId createArrayType(TypeId pointsTo);
 
     llvm::Type* getLlvmType(TypeId id, llvm::LLVMContext& llvmCtxt);
+
+    void createLlvmTypes(llvm::LLVMContext& llvmCtxt);
 };
 
 #endif // QLOW_SEM_CONTEXT_H

+ 1 - 1
src/sem/Semantic.h

@@ -434,7 +434,7 @@ struct qlow::sem::MethodCallExpression : public Expression
     
     inline MethodCallExpression(std::unique_ptr<Expression> target,
                                 Method* callee) :
-        Expression{ target->context, callee->returnType },
+        Expression{ callee->context, callee->returnType },
         callee{ callee },
         target{ std::move(target) }
     {

+ 34 - 11
src/sem/Type.cpp

@@ -24,7 +24,6 @@ Type::Type(Context& context, Union type, TypeId id) :
 
 
 Type::Type(Context& context, Union type, std::string name, TypeId id) :
-    name{ std::move(name) },
     type{ std::move(type) }
 {
     if (getKind() == Kind::NATIVE) {
@@ -52,25 +51,29 @@ Type::Kind Type::getKind(void) const
 }
 
 
+Type::Native Type::getNativeKind(void) const
+{
+    return std::get<NativeType>(this->type).type;
+}
+
+
 std::string Type::asString(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 this->name;
+                return "native";
             }
             else if constexpr (std::is_same<T, ClassType>::value) {
-                return this->name;
+                return this->getClass()->name;
             }
             else if constexpr (std::is_same<T, PointerType>::value) {
-                // TODO rewrite
-                //return context.getType(t.targetType) + "*";
-                return "*";
+                return this->typeScope->getContext().getType(t.targetType).asString() + "*";
             }
             else if constexpr (std::is_same<T, ArrayType>::value) {
-                //return "[" + context.getType(t.targetType) + "]";
-                return "[]";
+                return "["s + this->typeScope->getContext().getType(t.targetType).asString() + "]";
             }
         }
         ,
@@ -81,14 +84,34 @@ std::string Type::asString(void) const
 
 size_t Type::hash(void) const
 {
-    // TODO implement
-    return type.index() * 2345325 + std::hash<std::string>()(name);
+    auto value1 = std::visit(
+        [&] (const auto& t) -> size_t {
+            using T = std::decay_t<decltype(t)>;
+            if constexpr (std::is_same<T, NativeType>::value) {
+                return static_cast<size_t>(t.type) * 2345279;
+            }
+            else if constexpr (std::is_same<T, ClassType>::value) {
+                return reinterpret_cast<size_t>(t.classType) * 1;
+            }
+            else if constexpr (std::is_same<T, PointerType>::value) {
+                return t.targetType * 143115587;
+            }
+            else if constexpr (std::is_same<T, ArrayType>::value) {
+                //return "[" + context.getType(t.targetType) + "]";
+                return t.targetType * 2342345;
+            }
+        },
+        type
+    );
+    auto h = type.index() * 11111111111111111 + value1;
+    Printer::getInstance() << h << std::endl;
+    return h;
 }
 
 
 bool Type::operator==(const Type& other) const
 {
-    return this->name == other.name &&
+    return //this->name == other.name &&
            this->type == other.type;
 }
 

+ 2 - 1
src/sem/Type.h

@@ -89,7 +89,6 @@ private:
 
     using Union = std::variant<NativeType, ClassType, PointerType, ArrayType>;
 
-    std::string name;
     std::unique_ptr<TypeScope> typeScope;
     Union type;
 
@@ -104,6 +103,8 @@ public:
     Type& operator = (Type&& other) = default;
 
     Kind getKind(void) const;
+    Native getNativeKind(void) const;
+
     std::string asString(void) const;
     size_t hash(void) const;
 

+ 8 - 4
src/test.qlw

@@ -15,7 +15,7 @@ fast_fibonacci(i: Integer): Integer do
     return a
 end
 
-//extern do_shit
+extern printint(x: Integer)
 
 
 /*
@@ -30,9 +30,13 @@ end
 */
 
 main: Integer do
-    value: Integer
-    value := 42
-    return value
+    count: Integer
+    count := 0
+    while count != 20 do
+        printint(fast_fibonacci(count))
+        count := count + 1
+    end
+    return 0
     //do_shit
 end