/** ** \file llvmtranslate/llvm-type-visitor.cc ** \brief Implementation of llvmtranslator::LLVMTypeVisitor. */ #include #include #include namespace llvmtranslate { LLVMTypeVisitor::LLVMTypeVisitor(llvm::LLVMContext& ctx) : ctx_{ctx} {} llvm::Type* LLVMTypeVisitor::llvm_type_get() { return type_; } llvm::Type* LLVMTypeVisitor::get_record_ltype(const type::Record* e) { return structs_[e]; } llvm::Type* LLVMTypeVisitor::llvm_type(const type::Type& type) { operator()(type); return type_; } void LLVMTypeVisitor::operator()(const type::Nil& e) { if (auto record_type = e.record_type_get()) type_ = llvm_type(*record_type); else unreachable(); } void LLVMTypeVisitor::operator()(const type::Void&) { // FIXME DONE: Some code was deleted here (Void types can be interpreted as int or void type). // Je cite : "a variable can hold a void value (that are represented using an integer in LLVM)" // Mais du coup, je sais pas ce qui détermine quel type on lui donne. // En attendant je mets void tout le temps jusqu'à ce qu'on trouve pourquoi on le mettrait à int // Y a un monde où ça se gère au dessus (genre les vardecs et les assignexp ?) // Source : Un YAKA qui dit que en gros on a le choix mais qu'il vaut mieux le représenter comme int // Du coup pour le distinguer c'est un int sur 0 bits type_ = llvm::Type::getIntNTy(ctx_,0); } void LLVMTypeVisitor::operator()(const type::Int&) { type_ = llvm::Type::getInt32Ty(ctx_); } void LLVMTypeVisitor::operator()(const type::String&) { // Strings are pointers to characters in LLVM. // FIXME DONE: Some code was deleted here. // Bon vu qu'on a pas accès à la taille de la string on y va yolo. // Du coup c'est un PointerType de Int8 (du coup 8 bits pour un char) type_ = llvm::PointerType::get(llvm::Type::getInt8Ty(ctx_), 0); } void LLVMTypeVisitor::operator()(const type::Named& e) { // FIXME DONE: Some code was deleted here. llvm_type(e.actual()); const std::string reference_name = e.name_get().get(); if (const auto record_ref = dynamic_cast(&e.type_get()->actual()); record_ref != nullptr && structs_[record_ref]->getName() != reference_name) { structs_[record_ref]->setName(reference_name); } } void LLVMTypeVisitor::operator()(const type::Record& e) { // If the record was never translated, translate it if (!structs_[&e]) { // We need to create the struct in two passes to support recursive // types, like 'type a = { next : a } // So, first we create an empty struct structs_[&e] = llvm::StructType::create(ctx_); // Then set the body of the structure std::vector field_types; field_types.reserve(e.fields_get().size()); // FIXME DONE: Some code was deleted here. //Martial: Copy and convert the fields ig for (const auto& field : e.fields_get()) { super_type::operator()(field.type_get()); field_types.push_back(type_); } //Martial: Set the body with the converted types structs_[&e]->setBody(std::move(field_types), false); } type_ = llvm::PointerType::getUnqual(structs_[&e]); } void LLVMTypeVisitor::operator()(const type::Array& e) { // Arrays are pointers to the array elements, like in C. // FIXME DONE: Some code was deleted here. llvm_type(*e.get_element_type()); type_ = llvm::PointerType::getUnqual(type_); } } // namespace llvmtranslate