diff --git a/examples/a.glx b/examples/a.glx index 1a18d70..bfc2e91 100644 --- a/examples/a.glx +++ b/examples/a.glx @@ -1,6 +1,11 @@ -def main( ) -> int: - int num := 3; - int quatro := num + 1; - return quatro; -end; +def tigres_de_bengala( int numero) -> int: + int num := numero; + int quatro := num + 1; + return numero ; +end; +def main( ) -> int: + int num := 3; + int quatro := num + 1; + return tigres_de_bengala( quatro) ; ; +end; diff --git a/include/backend/generator/parallel/queue.hpp b/include/backend/generator/parallel/queue.hpp new file mode 100644 index 0000000..8288b37 --- /dev/null +++ b/include/backend/generator/parallel/queue.hpp @@ -0,0 +1,28 @@ +#ifndef QUEUE_H +#define QUEUE_H + +extern "C" { + #include "frontend/ast/definitions.h" +} + +#include +#include +#include +#include + +struct PendingIdentifier { + IdentifierNode *node; + std::promise promise; +}; + +// Tabela de símbolos e fila de pendências +extern std::mutex symbolTableMutex; +extern std::queue pendingQueue; +extern std::condition_variable pendingCondition; + +llvm::Value* find_or_wait_for_identifier(IdentifierNode *node); + +void process_pending_identifiers_async(); +void process_pending_identifiers_periodically(); + +#endif // QUEUE_H \ No newline at end of file diff --git a/include/backend/generator/symbols/symbol_stack.hpp b/include/backend/generator/symbols/symbol_stack.hpp index f47e137..ec7f94b 100644 --- a/include/backend/generator/symbols/symbol_stack.hpp +++ b/include/backend/generator/symbols/symbol_stack.hpp @@ -5,6 +5,7 @@ #include #include #include +#include // Include for std::mutex struct SymbolInfo { llvm::Value* value; @@ -14,7 +15,9 @@ struct SymbolInfo { using SymbolTable = std::unordered_map; extern std::stack symbol_stack; +extern std::mutex symbol_stack_mutex; + void enter_scope(void); void exit_scope(void); -#endif // SYMBOL_STACK_H \ No newline at end of file +#endif // SYMBOL_STACK_H diff --git a/include/frontend/checker/common_types.h b/include/frontend/checker/common_types.hpp similarity index 100% rename from include/frontend/checker/common_types.h rename to include/frontend/checker/common_types.hpp diff --git a/include/frontend/checker/core.h b/include/frontend/checker/core.hpp similarity index 100% rename from include/frontend/checker/core.h rename to include/frontend/checker/core.hpp diff --git a/src/backend/generator/expressions/generate_call.cpp b/src/backend/generator/expressions/generate_call.cpp index 74c9e51..7cead40 100644 --- a/src/backend/generator/expressions/generate_call.cpp +++ b/src/backend/generator/expressions/generate_call.cpp @@ -35,6 +35,10 @@ llvm::Value *generate_call(CallNode *call_node, llvm::LLVMContext &Context, llvm arg = Builder.CreateIntCast(arg, expected_type, true); } else if (arg->getType()->isFloatingPointTy() && expected_type->isFloatingPointTy()) { arg = Builder.CreateFPCast(arg, expected_type); + } else if (arg->getType()->isPointerTy() && expected_type->isIntegerTy()) { + arg = Builder.CreatePointerCast(arg, expected_type); + } else if (arg->getType()->isPointerTy() && expected_type->isFloatingPointTy()) { + arg = Builder.CreatePointerCast(arg, expected_type); } else { throw std::runtime_error("Argument type mismatch."); } diff --git a/src/backend/generator/expressions/generate_expr.cpp b/src/backend/generator/expressions/generate_expr.cpp index f8be31b..2987dd1 100644 --- a/src/backend/generator/expressions/generate_expr.cpp +++ b/src/backend/generator/expressions/generate_expr.cpp @@ -1,7 +1,3 @@ -#include -#include -#include -#include #include "backend/generator/expressions/generate_expr.hpp" #include "backend/generator/expressions/generate_numeric_literal.hpp" #include "backend/generator/expressions/generate_identifier.hpp" diff --git a/src/backend/generator/expressions/generate_identifier.cpp b/src/backend/generator/expressions/generate_identifier.cpp index 4859d65..f23abf3 100644 --- a/src/backend/generator/expressions/generate_identifier.cpp +++ b/src/backend/generator/expressions/generate_identifier.cpp @@ -1,12 +1,12 @@ #include "backend/generator/expressions/generate_identifier.hpp" #include "backend/generator/symbols/identifier_symbol_table.hpp" +#include "backend/generator/parallel/queue.hpp" llvm::Value *generate_identifier(IdentifierNode *node) { - const SymbolInfo *id = find_identifier(node->symbol); - - if (!id) { + try { + return find_or_wait_for_identifier(node); + } catch (...) { throw std::runtime_error("Error: identifier not found!"); } - - return id->value; } + diff --git a/src/backend/generator/generator.cpp b/src/backend/generator/generator.cpp index 052da3f..5fa4ed7 100644 --- a/src/backend/generator/generator.cpp +++ b/src/backend/generator/generator.cpp @@ -1,25 +1,70 @@ -#include #include "backend/generator/generate_ir.hpp" #include "backend/generator/statements/generate_stmt.hpp" +#include +#include -std::vector generate_ir(AstNode *node, llvm::LLVMContext &Context, llvm::Module &Module, llvm::IRBuilder<> &Builder) { - // Cast the AstNode to ProgramNode as the data in AstNode is assumed to be a ProgramNode - ProgramNode *program = (ProgramNode *)node->data; +// Estrutura intermediária personalizada para armazenar informações de IR +struct IntermediateIR { + std::string blockName; + std::vector instructions; +}; - // Vector to hold the generated LLVM IR values - std::vector IRs; +// Função principal de geração +std::vector generate_ir(AstNode *node, llvm::LLVMContext &mainContext, llvm::Module &mainModule, llvm::IRBuilder<> &mainBuilder) { + ProgramNode *program = static_cast(node->data); + std::vector> futures; + std::vector intermediateIRs; - // Iterate over all statements in the program and generate their corresponding IR + // Geração paralela de IR for (size_t i = 0; i < program->statement_count; ++i) { - // Generate LLVM IR for each statement - llvm::Value *IR = generate_stmt(program->statements[i], Context, Module, Builder); - - // If the generated IR is not null, add it to the result vector - if (IR) { - IRs.push_back(IR); + AstNode *statement = program->statements[i]; + + futures.push_back(std::async(std::launch::async, [statement]() -> IntermediateIR { + // Criar estrutura intermediária para esta thread + IntermediateIR ir; + ir.blockName = "Block_" + std::to_string(std::hash{}(std::this_thread::get_id())); + + // Criar contexto, módulo e IRBuilder para esta thread + llvm::LLVMContext threadContext; + llvm::Module threadModule("ThreadModule", threadContext); + llvm::IRBuilder<> threadBuilder(threadContext); + + llvm::Value* result = generate_stmt(statement, threadContext, threadModule, threadBuilder); + if (auto *inst = llvm::dyn_cast(result)) { + ir.instructions.push_back(inst); // Adicionar instrução gerada + } + + return ir; + })); + } + + // Coletar resultados das threads + for (auto &future : futures) { + try { + intermediateIRs.push_back(future.get()); + } catch (const std::exception &e) { + llvm::errs() << "Exception during future.get(): " << e.what() << "\n"; + } catch (...) { + llvm::errs() << "Unknown exception during future.get()\n"; + } + } + + // Concatenar IRs intermediários no contexto principal + for (const auto &ir : intermediateIRs) { + // Criar um novo bloco no contexto principal + + /* + * O segfault ocorre no getParent + */ + + llvm::BasicBlock *block = llvm::BasicBlock::Create(mainContext, ir.blockName, mainBuilder.GetInsertBlock()->getParent()); + mainBuilder.SetInsertPoint(block); // Estabelecer ponto de inserção no novo bloco + + // Inserir as instruções no bloco + for (auto *inst : ir.instructions) { + mainBuilder.Insert(inst); // Adicionar instrução ao bloco principal } } - // Return the vector containing the generated IR for the statements - return IRs; + return {}; } diff --git a/src/backend/generator/generator.test.cpp b/src/backend/generator/generator.test.cpp index 067ef08..e63a341 100644 --- a/src/backend/generator/generator.test.cpp +++ b/src/backend/generator/generator.test.cpp @@ -19,6 +19,7 @@ #include "backend/generator/generate_ir.hpp" #include "backend/generator/symbols/symbol_stack.hpp" +#include "backend/generator/parallel/queue.hpp" extern "C" { #include "frontend/lexer/core.h" @@ -66,6 +67,9 @@ int main(int argc, char **argv) { printf("-----------------\n"); print_ast(ast); + printf("\nGeneration:\n"); + printf("-----------------\n"); + // Initialize LLVM target-related components (needed to generate machine code) llvm::InitializeAllTargetInfos(); llvm::InitializeAllTargets(); @@ -81,7 +85,9 @@ int main(int argc, char **argv) { // Create the global scope enter_scope(); - // Generate the LLVM IR from the AST + std::thread pendingThread(process_pending_identifiers_periodically); + pendingThread.detach(); + std::vector values = generate_ir(ast, TheContext, TheModule, Builder); // Print out the generated LLVM IR for debugging diff --git a/src/backend/generator/parallel/queue.cpp b/src/backend/generator/parallel/queue.cpp new file mode 100644 index 0000000..2086af7 --- /dev/null +++ b/src/backend/generator/parallel/queue.cpp @@ -0,0 +1,62 @@ +#include "backend/generator/expressions/generate_identifier.hpp" +#include "backend/generator/symbols/identifier_symbol_table.hpp" +#include "backend/generator/parallel/queue.hpp" + +std::mutex symbolTableMutex; +std::queue pendingQueue; +std::condition_variable pendingCondition; + +// Função para encontrar um identificador ou adicionar à fila de pendências +llvm::Value* find_or_wait_for_identifier(IdentifierNode* node) { + std::unique_lock lock(symbolTableMutex); + + // Tentar encontrar o identificador na tabela de símbolos + const SymbolInfo* id = find_identifier(node->symbol); + if (id) { + return id->value; + } + + // Se não encontrar, criar uma pendência + PendingIdentifier pending{node}; + std::promise promise; + pending.promise = std::move(promise); + auto future = pending.promise.get_future(); + + // Adicionar à fila de pendências + pendingQueue.push(std::move(pending)); + pendingCondition.notify_all(); + + lock.unlock(); // Desbloquear a tabela de símbolos para permitir outros acessos + + // Esperar pela resolução do identificador + return future.get(); +} + +// Processar as pendências de identificadores de forma assíncrona +void process_pending_identifiers_async() { + std::unique_lock lock(symbolTableMutex); + + // Processar a fila de pendências enquanto houver identificadores pendentes + while (!pendingQueue.empty()) { + PendingIdentifier pending = std::move(pendingQueue.front()); + pendingQueue.pop(); + + // Verificar novamente a tabela de símbolos + const SymbolInfo* id = find_identifier(pending.node->symbol); + if (id) { + // Resolver a pendência, setando o valor + pending.promise.set_value(id->value); + } else { + // Se não encontrar, re-adiciona à fila + pendingQueue.push(std::move(pending)); + } + } +} + +// Função para ser chamada em outro thread que processa as pendências +void process_pending_identifiers_periodically() { + while (true) { + process_pending_identifiers_async(); + } +} + diff --git a/src/backend/generator/statements/generate_stmt.cpp b/src/backend/generator/statements/generate_stmt.cpp index 679d2d0..6ea7349 100644 --- a/src/backend/generator/statements/generate_stmt.cpp +++ b/src/backend/generator/statements/generate_stmt.cpp @@ -3,31 +3,23 @@ #include "backend/generator/statements/generate_function_declaration_stmt.hpp" #include "backend/generator/statements/generate_extern_stmt.hpp" #include "backend/generator/expressions/generate_expr.hpp" -#include llvm::Value* generate_stmt(AstNode *node, llvm::LLVMContext &Context, llvm::Module &Module, llvm::IRBuilder<> &Builder) { switch (node->kind) { case NODE_VARIABLE: { VariableNode *varNode = (VariableNode *)node->data; - generate_variable_declaration_stmt(varNode, Context, Builder, Module); - - return nullptr; + return generate_variable_declaration_stmt(varNode, Context, Builder, Module); } case NODE_FUNCTION: { FunctionNode *funcNode = (FunctionNode *)node->data; - generate_function_declaration_stmt(funcNode, Context, Builder, Module); - - return nullptr; + return generate_function_declaration_stmt(funcNode, Context, Builder, Module); } case NODE_EXTERN: { ExternNode *externNode = (ExternNode *)node->data; - generate_extern_stmt(externNode, Context, Builder, Module); - - return nullptr; + return generate_extern_stmt(externNode, Context, Builder, Module); } - default: { - return generate_expr(node, Context, Builder, Module); + return generate_expr(node, Context, Builder, Module); // Para expressões, o valor gerado } } } diff --git a/src/backend/generator/statements/generate_variable_declaration_stmt.cpp b/src/backend/generator/statements/generate_variable_declaration_stmt.cpp index 03a9efc..81b549d 100644 --- a/src/backend/generator/statements/generate_variable_declaration_stmt.cpp +++ b/src/backend/generator/statements/generate_variable_declaration_stmt.cpp @@ -18,7 +18,10 @@ llvm::Value* generate_variable_declaration_stmt(VariableNode *node, llvm::LLVMCo } // Stores the allocated variable in the identifier symbol table - add_identifier(node->name, alloca, var_type); + { + std::lock_guard lock(symbol_stack_mutex); + add_identifier(node->name, alloca, var_type); + } return alloca; } diff --git a/src/backend/generator/symbols/identifier_symbol_table.cpp b/src/backend/generator/symbols/identifier_symbol_table.cpp index e30292b..20ca401 100644 --- a/src/backend/generator/symbols/identifier_symbol_table.cpp +++ b/src/backend/generator/symbols/identifier_symbol_table.cpp @@ -1,12 +1,15 @@ #include "backend/generator/symbols/identifier_symbol_table.hpp" #include "backend/generator/symbols/symbol_stack.hpp" -const SymbolInfo* find_identifier(const std::string &name) { +const SymbolInfo *find_identifier(const std::string &name) { + std::lock_guard lock(symbol_stack_mutex); + for (const auto& entry : symbol_stack.top()) { if (entry.first == name) { return &entry.second; } } + return nullptr; } diff --git a/src/backend/generator/symbols/symbol_stack.cpp b/src/backend/generator/symbols/symbol_stack.cpp index cc7c9b5..61e6901 100644 --- a/src/backend/generator/symbols/symbol_stack.cpp +++ b/src/backend/generator/symbols/symbol_stack.cpp @@ -1,15 +1,16 @@ #include "backend/generator/symbols/symbol_stack.hpp" +#include "backend/generator/symbols/identifier_symbol_table.hpp" std::stack symbol_stack; - +std::mutex symbol_stack_mutex; void enter_scope() { - // Adiciona uma nova tabela de símbolos ao topo da pilha + std::lock_guard lock(symbol_stack_mutex); symbol_stack.push(SymbolTable{}); } void exit_scope() { - // Remove a tabela de símbolos do topo da pilha + std::lock_guard lock(symbol_stack_mutex); if (symbol_stack.empty()) { throw std::runtime_error("Exiting scope when no scope exists!"); } diff --git a/src/frontend/checker/checker.cpp b/src/frontend/checker/checker.cpp new file mode 100644 index 0000000..79a92e7 --- /dev/null +++ b/src/frontend/checker/checker.cpp @@ -0,0 +1,11 @@ +#include + +extern "C" { + #include "frontend/checker/core.h" + #include "frontend/checker/common_types.h" + #include "utils.h" +} + +Checker* init(AstNode* ast) { + +}