From 1a362fdfdb26b8cda242164902e9a975180bf7c1 Mon Sep 17 00:00:00 2001 From: wesuRage Date: Thu, 19 Dec 2024 21:35:55 -0300 Subject: [PATCH 01/21] feat(for): implemented for loop generation --- .../statements/generate_for_stmt.hpp | 16 ++++ .../statements/generate_for_stmt.cpp | 74 +++++++++++++++++++ 2 files changed, 90 insertions(+) create mode 100644 include/backend/generator/statements/generate_for_stmt.hpp create mode 100644 src/backend/generator/statements/generate_for_stmt.cpp diff --git a/include/backend/generator/statements/generate_for_stmt.hpp b/include/backend/generator/statements/generate_for_stmt.hpp new file mode 100644 index 0000000..00e05e1 --- /dev/null +++ b/include/backend/generator/statements/generate_for_stmt.hpp @@ -0,0 +1,16 @@ +#ifndef GENERATE_FOR_STMT_H +#define GENERATE_FOR_STMT_H + +extern "C" { + #include "frontend/ast/definitions.h" +} +#include +#include +#include +#include +#include +#include + +llvm::Value* generate_for_stmt(ForNode *node, llvm::LLVMContext &Context, llvm::IRBuilder<> &Builder, llvm::Module &Module); + +#endif // GENERATE_FOR_STMT_H \ No newline at end of file diff --git a/src/backend/generator/statements/generate_for_stmt.cpp b/src/backend/generator/statements/generate_for_stmt.cpp new file mode 100644 index 0000000..47351b9 --- /dev/null +++ b/src/backend/generator/statements/generate_for_stmt.cpp @@ -0,0 +1,74 @@ +#include "backend/generator/expressions/generate_expr.hpp" +#include "backend/generator/statements/generate_stmt.hpp" +#include "backend/generator/statements/generate_for_stmt.hpp" +#include "backend/generator/statements/generate_variable_declaration_stmt.hpp" +#include "backend/generator/symbols/identifier_symbol_table.hpp" + +llvm::Value* generate_for_stmt(ForNode *node, llvm::LLVMContext &Context, llvm::IRBuilder<> &Builder, llvm::Module &Module) { + llvm::Function *currentFunction = Builder.GetInsertBlock()->getParent(); + + // Blocos básicos do loop + llvm::BasicBlock *preLoopBB = llvm::BasicBlock::Create(Context, "preloop", currentFunction); + llvm::BasicBlock *condBB = llvm::BasicBlock::Create(Context, "cond", currentFunction); + llvm::BasicBlock *bodyBB = llvm::BasicBlock::Create(Context, "body", currentFunction); + llvm::BasicBlock *updateBB = llvm::BasicBlock::Create(Context, "update", currentFunction); + llvm::BasicBlock *endBB = llvm::BasicBlock::Create(Context, "endloop", currentFunction); + + // Cria o salto para o bloco de pré-loop + Builder.CreateBr(preLoopBB); + Builder.SetInsertPoint(preLoopBB); + + // Declaração da variável do loop (%i) e inicialização + VariableNode iteratorVar; + iteratorVar.name = node->variable; + iteratorVar.varType = node->var_type; + iteratorVar.isPtr = node->var_isPtr; + iteratorVar.isConst = false; + iteratorVar.value = node->start; + + generate_variable_declaration_stmt(&iteratorVar, Context, Builder, Module); + + llvm::Value *startVal = generate_expr(node->start, Context, Builder, Module); + + llvm::AllocaInst *loopVar = Builder.CreateAlloca(startVal->getType(), nullptr, node->variable); + Builder.CreateStore(startVal, loopVar); // Inicializa %i + + Builder.CreateBr(condBB); + + // Condição do loop + Builder.SetInsertPoint(condBB); + llvm::Value *loopVarVal = Builder.CreateLoad(loopVar->getAllocatedType(), loopVar, node->variable); + + BinaryExprNode *binaryNode = (BinaryExprNode *)node->stop->data; + llvm::Value *rightOperand = generate_expr(binaryNode->right, Context, Builder, Module); + llvm::Value *stopVal = rightOperand; + + if (stopVal->getType()->isPointerTy()) { + const SymbolInfo *id = find_identifier(stopVal->getName().str()); + stopVal = id->value; + } + + llvm::Value *cond = Builder.CreateICmpSLT(loopVarVal, stopVal, "loopcond"); + + Builder.CreateCondBr(cond, bodyBB, endBB); // Se a condição for verdadeira, vai para o corpo; senão, para o final. + + // Corpo do loop + Builder.SetInsertPoint(bodyBB); + for (size_t i = 0; i < node->body_count; ++i) { + generate_stmt(node->body[i], Context, Module, Builder); // Gerar as declarações no corpo do loop + } + + Builder.CreateBr(updateBB); // Salta para o bloco de atualização + + // Atualiza o valor de %i + Builder.SetInsertPoint(updateBB); + llvm::Value *loopVarValUpdate = Builder.CreateLoad(loopVar->getAllocatedType(), loopVar, node->variable); + llvm::Value *inc = Builder.CreateAdd(loopVarValUpdate, llvm::ConstantInt::get(llvm::Type::getInt32Ty(Context), 1), "inc"); + Builder.CreateStore(inc, loopVar); // Atualiza %i + + Builder.CreateBr(condBB); // Salta de volta para a condição + + // Finaliza o loop + Builder.SetInsertPoint(endBB); + return Builder.CreateLoad(loopVar->getAllocatedType(), loopVar, node->variable); +} From fcedb57851d74126d5f5f572190f923116468bcb Mon Sep 17 00:00:00 2001 From: wesuRage Date: Thu, 19 Dec 2024 21:36:27 -0300 Subject: [PATCH 02/21] feat(symbols): added string symbol table --- .../generator/symbols/string_symbol_table.hpp | 13 +++++++++++++ .../generator/symbols/string_symbol_table.cpp | 15 +++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 include/backend/generator/symbols/string_symbol_table.hpp create mode 100644 src/backend/generator/symbols/string_symbol_table.cpp diff --git a/include/backend/generator/symbols/string_symbol_table.hpp b/include/backend/generator/symbols/string_symbol_table.hpp new file mode 100644 index 0000000..3edc997 --- /dev/null +++ b/include/backend/generator/symbols/string_symbol_table.hpp @@ -0,0 +1,13 @@ +#ifndef STRING_SYMBOL_TABLE_H +#define STRING_SYMBOL_TABLE_H + +#include +#include +#include + +extern std::unordered_map string_symbol_table; + +void add_string(const std::string &name, llvm::Value *value); +llvm::Value *find_string(const std::string &name); + +#endif // STRING_SYMBOL_TABLE_H \ No newline at end of file diff --git a/src/backend/generator/symbols/string_symbol_table.cpp b/src/backend/generator/symbols/string_symbol_table.cpp new file mode 100644 index 0000000..936e025 --- /dev/null +++ b/src/backend/generator/symbols/string_symbol_table.cpp @@ -0,0 +1,15 @@ +#include "backend/generator/symbols/string_symbol_table.hpp" + +std::unordered_map string_symbol_table; + +void add_string(const std::string &name, llvm::Value *value) { + string_symbol_table[name] = value; +} + +llvm::Value *find_string(const std::string &name) { + auto it = string_symbol_table.find(name); + if (it != string_symbol_table.end()) { + return it->second; + } + return nullptr; +} \ No newline at end of file From 07215b082ce401acb74521161f8ae3ba2b3f7b53 Mon Sep 17 00:00:00 2001 From: wesuRage Date: Thu, 19 Dec 2024 21:37:24 -0300 Subject: [PATCH 03/21] feat(symbols): improved identifier symbol table --- include/backend/generator/symbols/identifier_symbol_table.hpp | 2 +- src/backend/generator/symbols/identifier_symbol_table.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/backend/generator/symbols/identifier_symbol_table.hpp b/include/backend/generator/symbols/identifier_symbol_table.hpp index 39d1ccd..5cc9588 100644 --- a/include/backend/generator/symbols/identifier_symbol_table.hpp +++ b/include/backend/generator/symbols/identifier_symbol_table.hpp @@ -7,6 +7,6 @@ #include "backend/generator/symbols/symbol_stack.hpp" const SymbolInfo *find_identifier(const std::string &name); -void add_identifier(const std::string &name, llvm::Value* value, llvm::Type* type); +void add_identifier(const std::string &name, llvm::Value* declaration, llvm::Value* value, llvm::Type* type); #endif // IDENTIFIER_SYMBOL_TABLE_H \ No newline at end of file diff --git a/src/backend/generator/symbols/identifier_symbol_table.cpp b/src/backend/generator/symbols/identifier_symbol_table.cpp index 20ca401..2f2ca1c 100644 --- a/src/backend/generator/symbols/identifier_symbol_table.cpp +++ b/src/backend/generator/symbols/identifier_symbol_table.cpp @@ -13,9 +13,9 @@ const SymbolInfo *find_identifier(const std::string &name) { return nullptr; } -void add_identifier(const std::string& name, llvm::Value* value, llvm::Type* type) { +void add_identifier(const std::string& name, llvm::Value* declaration, llvm::Value* value, llvm::Type* type) { if (symbol_stack.empty()) { throw std::runtime_error("No active scope to add identifier."); } - symbol_stack.top()[name] = SymbolInfo{value, type}; + symbol_stack.top()[name] = SymbolInfo{declaration, value, type}; } \ No newline at end of file From e65b986ff8bc57571d9996dd2c7b0f9b7a3f1d9f Mon Sep 17 00:00:00 2001 From: wesuRage Date: Thu, 19 Dec 2024 21:38:01 -0300 Subject: [PATCH 04/21] fix(deparallelized): removed parallelization temporarely --- src/backend/generator/generator.cpp | 77 ++++++----------------------- 1 file changed, 16 insertions(+), 61 deletions(-) diff --git a/src/backend/generator/generator.cpp b/src/backend/generator/generator.cpp index 5fa4ed7..bfacade 100644 --- a/src/backend/generator/generator.cpp +++ b/src/backend/generator/generator.cpp @@ -1,70 +1,25 @@ +#include #include "backend/generator/generate_ir.hpp" #include "backend/generator/statements/generate_stmt.hpp" -#include -#include -// Estrutura intermediária personalizada para armazenar informações de IR -struct IntermediateIR { - std::string blockName; - std::vector instructions; -}; +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; -// 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; + // Vector to hold the generated LLVM IR values + std::vector IRs; - // Geração paralela de IR + // Iterate over all statements in the program and generate their corresponding IR for (size_t i = 0; i < program->statement_count; ++i) { - 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 + // 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); } } - return {}; -} + // Return the vector containing the generated IR for the statements + return IRs; +} \ No newline at end of file From bfe618ec5944ff937ba2e99108b01f25fd9d2777 Mon Sep 17 00:00:00 2001 From: wesuRage Date: Thu, 19 Dec 2024 21:38:57 -0300 Subject: [PATCH 05/21] feat(parallel): features to the parallel for statement --- include/frontend/ast/definitions.h | 12 ++++++++++++ include/frontend/lexer/core.h | 3 +++ src/frontend/lexer/lexer.c | 11 ++++++++--- 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/include/frontend/ast/definitions.h b/include/frontend/ast/definitions.h index a3e9b2b..7471ec5 100644 --- a/include/frontend/ast/definitions.h +++ b/include/frontend/ast/definitions.h @@ -94,8 +94,20 @@ typedef struct { AstNode *stop; AstNode *updater; AstNode *iterator; + bool is_parallel; + char *schedule_policy; // "static", "dynamic" + AstNode *num_threads; } ForNode; +typedef struct { + char *type; // "barrier", "atomic" +} SyncNode; + +typedef struct { + char *name; + char *memory_type; // "private", "shared", "pgas" +} MemoryNode; + typedef struct { AstNode *condition; AstNode **consequent; diff --git a/include/frontend/lexer/core.h b/include/frontend/lexer/core.h index 1d44951..d288a99 100644 --- a/include/frontend/lexer/core.h +++ b/include/frontend/lexer/core.h @@ -73,6 +73,9 @@ typedef enum { TOKEN_OBRACKET, TOKEN_CBRACKET, TOKEN_EXTERN, + TOKEN_STATIC, + TOKEN_DYNAMIC, + TOKEN_PARALLEL, TOKEN_UNKNOWN, } TokenType; diff --git a/src/frontend/lexer/lexer.c b/src/frontend/lexer/lexer.c index ec22524..7f338e7 100644 --- a/src/frontend/lexer/lexer.c +++ b/src/frontend/lexer/lexer.c @@ -37,7 +37,6 @@ void initLexer(FILE *source, const char *file) { * Advances the lexer past spaces, tabs, and newlines, updating line, column, and position counters. */ void skipWhitespace() { - while (isspace(currentChar)) { if (currentChar == '\n') { line++; @@ -128,6 +127,9 @@ char pick_next() { */ TokenType match_keyword(const char *lexeme) { if (strcmp(lexeme, "extern") == 0) return TOKEN_EXTERN; + if (strcmp(lexeme, "parallel") == 0) return TOKEN_PARALLEL; + if (strcmp(lexeme, "static") == 0) return TOKEN_STATIC; + if (strcmp(lexeme, "dynamic") == 0) return TOKEN_DYNAMIC; if (strcmp(lexeme, "for") == 0) return TOKEN_FOR; if (strcmp(lexeme, "if") == 0) return TOKEN_IF; if (strcmp(lexeme, "elif") == 0) return TOKEN_ELIF; @@ -420,12 +422,15 @@ Token getNextToken() { } // Unknown character + ungetc(currentChar, src); + ungetc(currentChar, src); + currentChar = fgetc(src); lexer_error( filename, line, - col, + col - 1, + position - 1, position - 1, - position, currentChar, "Invalid character" ); From 346253992ffe088d9c5a5cad45d693ebf25e4625 Mon Sep 17 00:00:00 2001 From: wesuRage Date: Thu, 19 Dec 2024 21:39:57 -0300 Subject: [PATCH 06/21] feat(declaration): improved declaration for uninitialized variables --- src/frontend/parser/statements/parse_stmt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/frontend/parser/statements/parse_stmt.c b/src/frontend/parser/statements/parse_stmt.c index c100620..cbdda33 100644 --- a/src/frontend/parser/statements/parse_stmt.c +++ b/src/frontend/parser/statements/parse_stmt.c @@ -49,7 +49,7 @@ AstNode *parse_stmt(Parser *parser) { } // If it's determined to be a variable declaration, handle it. - if (isDeclaration) { + if (isDeclaration || strcmp(type, "implicit") == 1) { bool isPtr = false; // Check if the variable is a pointer by looking for a "*" token. if (current_token(parser).type == TOKEN_MUL) { From ef735b90cf0c39f1508905a210d540a8d0a24f50 Mon Sep 17 00:00:00 2001 From: wesuRage Date: Thu, 19 Dec 2024 21:40:31 -0300 Subject: [PATCH 07/21] feat(parallel): parsing parallel for statement --- .../parser/statements/parse_for_stmt.c | 40 +++++++++++++++++-- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/src/frontend/parser/statements/parse_for_stmt.c b/src/frontend/parser/statements/parse_for_stmt.c index df07842..1a4df75 100644 --- a/src/frontend/parser/statements/parse_for_stmt.c +++ b/src/frontend/parser/statements/parse_for_stmt.c @@ -16,12 +16,34 @@ AstNode *parse_for_stmt(Parser *parser) { int position_start = current_token(parser).position_start; consume_token(parser); + bool var_isPtr = false, + is_parallel = false; + + char *var_type = "int", + *variable = NULL, + *schedule_policy = NULL; + + AstNode *iterator = NULL, + *start = NULL, + *stop = NULL, + *updater = NULL, + *num_threads = NULL; + + if (current_token(parser).type == TOKEN_PARALLEL) { + consume_token(parser); + is_parallel = true; + + if (current_token(parser).type != TOKEN_STATIC && current_token(parser).type != TOKEN_DYNAMIC) { + error(parser, "Expected schedule policy"); + exit(EXIT_FAILURE); + } + + schedule_policy = consume_token(parser).lexeme; + } + + expect(parser, TOKEN_OPAREN, "Expected \"(\"."); - char *var_type = "int"; - bool var_isPtr = false; - char *variable = NULL; - AstNode *iterator = NULL, *start = NULL, *stop = NULL, *updater = NULL; if (current_token(parser).type != TOKEN_IDENTIFIER) { var_type = parse_type(parser); @@ -35,10 +57,12 @@ AstNode *parse_for_stmt(Parser *parser) { if (current_token(parser).type == TOKEN_ASSIGN) { consume_token(parser); + printf("Token: %s\n", current_token(parser).lexeme); start = parse_expr(parser); expect(parser, TOKEN_SEMICOLON, "Expected \";\"."); + printf("Token: %s\n", current_token(parser).lexeme); stop = parse_logical_expr(parser); expect(parser, TOKEN_SEMICOLON, "Expected \";\"."); @@ -62,6 +86,11 @@ AstNode *parse_for_stmt(Parser *parser) { expect(parser, TOKEN_CPAREN, "Expected \")\"."); + if (current_token(parser).type == TOKEN_ARROW) { + consume_token(parser); + num_threads = parse_expr(parser); + } + expect(parser, TOKEN_COLON, "Expected \":\"."); ForNode *for_data = MALLOC_S(sizeof(ForNode)); @@ -74,6 +103,9 @@ AstNode *parse_for_stmt(Parser *parser) { for_data->stop = stop; for_data->updater = updater; for_data->iterator = iterator; + for_data->is_parallel = is_parallel; + for_data->schedule_policy = schedule_policy; + for_data->num_threads = num_threads; while (not_eof(parser) && current_token(parser).type != TOKEN_END) { for_data->body = REALLOC_S( From 6b43b7005802c8b9a3703459f4771f026d395ffa Mon Sep 17 00:00:00 2001 From: wesuRage Date: Thu, 19 Dec 2024 21:41:07 -0300 Subject: [PATCH 08/21] feat(parallel): printing parallel features of for loop --- .../parser/printer/nodes/statements/print_for.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/frontend/parser/printer/nodes/statements/print_for.c b/src/frontend/parser/printer/nodes/statements/print_for.c index 22bde79..c313f6e 100644 --- a/src/frontend/parser/printer/nodes/statements/print_for.c +++ b/src/frontend/parser/printer/nodes/statements/print_for.c @@ -23,6 +23,7 @@ void print_for(const AstNode *node, int depth, VisitedNodes *visited) { print_indent(depth + 2); printf("Is Pointer: %s\n", for_node->var_isPtr ? "true" : "false"); + if (for_node->iterator) { print_indent(depth + 1); printf("Iterator:\n"); @@ -43,6 +44,19 @@ void print_for(const AstNode *node, int depth, VisitedNodes *visited) { } } + print_indent(depth + 1); + printf("Is Parallel: %s\n", for_node->is_parallel ? "true" : "false"); + + if (for_node->is_parallel) { + print_indent(depth + 1); + printf("Scheduling Policy: %s\n", for_node->schedule_policy); + + print_indent(depth + 1); + printf("Number of Threads: \n"); + + print_ast_node(for_node->num_threads, depth + 2, visited); + } + if (for_node->body_count > 0) { print_indent(depth + 1); printf("Body:\n"); From 7964a1da9e3c7643d6215a2050ea8624eeade425 Mon Sep 17 00:00:00 2001 From: wesuRage Date: Thu, 19 Dec 2024 21:42:05 -0300 Subject: [PATCH 09/21] feat(identifier): better identifier formating on the symbol table --- .../generator/statements/generate_extern_stmt.cpp | 10 +++++++--- .../generate_function_declaration_stmt.cpp | 2 +- .../generate_variable_declaration_stmt.cpp | 12 ++++++------ 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/backend/generator/statements/generate_extern_stmt.cpp b/src/backend/generator/statements/generate_extern_stmt.cpp index 1e0b5ac..41feb44 100644 --- a/src/backend/generator/statements/generate_extern_stmt.cpp +++ b/src/backend/generator/statements/generate_extern_stmt.cpp @@ -2,6 +2,7 @@ #include "backend/generator/types/generate_type.hpp" #include "backend/generator/symbols/function_symbol_table.hpp" #include "backend/generator/symbols/identifier_symbol_table.hpp" +#include "backend/generator/parallel/queue.hpp" llvm::Value* generate_extern_stmt(ExternNode *node, llvm::LLVMContext &Context, llvm::IRBuilder<> &Builder, llvm::Module &Module) { if (!node || !node->type || !node->identifier) { @@ -35,7 +36,7 @@ llvm::Value* generate_extern_stmt(ExternNode *node, llvm::LLVMContext &Context, function_symbol_table[node->identifier] = function; - return function; // Return the function declaration + return function; } else if (strcmp(node->extern_type, "variable") == 0) { // Handle variable declaration llvm::GlobalVariable *global_var = llvm::cast( @@ -44,9 +45,12 @@ llvm::Value* generate_extern_stmt(ExternNode *node, llvm::LLVMContext &Context, global_var->setLinkage(llvm::GlobalValue::ExternalLinkage); - add_identifier(node->identifier, global_var, decl_type); + { + std::unique_lock lock(symbolTableMutex); + add_identifier(node->identifier, global_var, nullptr, decl_type); + } - return global_var; // Return the variable declaration + return global_var; } else { throw std::runtime_error("Unsupported extern type: " + std::string(node->extern_type)); } diff --git a/src/backend/generator/statements/generate_function_declaration_stmt.cpp b/src/backend/generator/statements/generate_function_declaration_stmt.cpp index 227605b..5c9df45 100644 --- a/src/backend/generator/statements/generate_function_declaration_stmt.cpp +++ b/src/backend/generator/statements/generate_function_declaration_stmt.cpp @@ -37,7 +37,7 @@ llvm::Value* generate_function_declaration_stmt(FunctionNode *node, llvm::LLVMCo llvm::Type *type = generate_type(param->type, Context); // Stores in the identifier symbol table - add_identifier(param->name, &arg, type); + add_identifier(param->name, &arg, nullptr, type); ++idx; } diff --git a/src/backend/generator/statements/generate_variable_declaration_stmt.cpp b/src/backend/generator/statements/generate_variable_declaration_stmt.cpp index 81b549d..563e88c 100644 --- a/src/backend/generator/statements/generate_variable_declaration_stmt.cpp +++ b/src/backend/generator/statements/generate_variable_declaration_stmt.cpp @@ -15,12 +15,12 @@ llvm::Value* generate_variable_declaration_stmt(VariableNode *node, llvm::LLVMCo // Store the initialized value into the allocated space (AllocaInst) Builder.CreateStore(init_value, alloca); - } - - // Stores the allocated variable in the identifier symbol table - { - std::lock_guard lock(symbol_stack_mutex); - add_identifier(node->name, alloca, var_type); + + // Stores the allocated variable in the identifier symbol table + { + std::lock_guard lock(symbol_stack_mutex); + add_identifier(node->name, alloca, init_value, var_type); + } } return alloca; From 540ee9ba0f50caccf0f74e580ceef9ba3e1a0795 Mon Sep 17 00:00:00 2001 From: wesuRage Date: Thu, 19 Dec 2024 21:42:25 -0300 Subject: [PATCH 10/21] feat(for): added for node --- src/backend/generator/statements/generate_stmt.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/backend/generator/statements/generate_stmt.cpp b/src/backend/generator/statements/generate_stmt.cpp index 6ea7349..2264cb4 100644 --- a/src/backend/generator/statements/generate_stmt.cpp +++ b/src/backend/generator/statements/generate_stmt.cpp @@ -2,6 +2,7 @@ #include "backend/generator/statements/generate_variable_declaration_stmt.hpp" #include "backend/generator/statements/generate_function_declaration_stmt.hpp" #include "backend/generator/statements/generate_extern_stmt.hpp" +#include "backend/generator/statements/generate_for_stmt.hpp" #include "backend/generator/expressions/generate_expr.hpp" llvm::Value* generate_stmt(AstNode *node, llvm::LLVMContext &Context, llvm::Module &Module, llvm::IRBuilder<> &Builder) { @@ -14,6 +15,10 @@ llvm::Value* generate_stmt(AstNode *node, llvm::LLVMContext &Context, llvm::Modu FunctionNode *funcNode = (FunctionNode *)node->data; return generate_function_declaration_stmt(funcNode, Context, Builder, Module); } + case NODE_FOR: { + ForNode *forNode = (ForNode *)node->data; + return generate_for_stmt(forNode, Context, Builder, Module); + } case NODE_EXTERN: { ExternNode *externNode = (ExternNode *)node->data; return generate_extern_stmt(externNode, Context, Builder, Module); From c8d0d2fd28ea2602c9d947b1ee083bb456ebddb7 Mon Sep 17 00:00:00 2001 From: wesuRage Date: Thu, 19 Dec 2024 21:43:08 -0300 Subject: [PATCH 11/21] feat(parallel): better results for identifier lookup --- src/backend/generator/parallel/queue.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/backend/generator/parallel/queue.cpp b/src/backend/generator/parallel/queue.cpp index 2086af7..aee0f26 100644 --- a/src/backend/generator/parallel/queue.cpp +++ b/src/backend/generator/parallel/queue.cpp @@ -5,15 +5,20 @@ std::mutex symbolTableMutex; std::queue pendingQueue; std::condition_variable pendingCondition; +std::string global_id_return; // Função para encontrar um identificador ou adicionar à fila de pendências -llvm::Value* find_or_wait_for_identifier(IdentifierNode* node) { +llvm::Value* find_or_wait_for_identifier(IdentifierNode* node, std::string return_type) { 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; + if (return_type == "declaration") { + return id->declaration; + } else { + return id->value; + } } // Se não encontrar, criar uma pendência From 6c28f8c304ad20b411199cf5dad3fc0077fad55d Mon Sep 17 00:00:00 2001 From: wesuRage Date: Thu, 19 Dec 2024 21:44:11 -0300 Subject: [PATCH 12/21] feat(strings): better string generation --- .../generator/expressions/generate_string.cpp | 43 +++++++++++-------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/src/backend/generator/expressions/generate_string.cpp b/src/backend/generator/expressions/generate_string.cpp index 4a70c5f..33adbd1 100644 --- a/src/backend/generator/expressions/generate_string.cpp +++ b/src/backend/generator/expressions/generate_string.cpp @@ -1,4 +1,5 @@ #include "backend/generator/expressions/generate_string.hpp" +#include "backend/generator/symbols/string_symbol_table.hpp" // Inclua o header da tabela de símbolos de strings llvm::Value *generate_string_literal(StringNode *string_node, llvm::LLVMContext &Context, llvm::IRBuilder<> &Builder, llvm::Module &Module) { // Ensure that the StringNode and the string data are valid @@ -6,28 +7,36 @@ llvm::Value *generate_string_literal(StringNode *string_node, llvm::LLVMContext throw std::runtime_error("Invalid string node: missing string value."); } - // This represents the string as a constant array of characters in LLVM + // Check if the string is already in the symbol table + llvm::Value *existing_string = find_string(string_node->string); + if (existing_string) { + return existing_string; // Return the existing string if found + } + // Create a constant representing the string, including the null terminator llvm::Constant *string_constant = llvm::ConstantDataArray::getString(Context, string_node->string, true); - // This global variable will hold the constant array - llvm::GlobalVariable *global_string = new llvm::GlobalVariable( - Module, // The module to which this global variable belongs - string_constant->getType(), // The type of the string constant (constant array of chars) - true, // Whether the variable is constant - llvm::GlobalValue::PrivateLinkage, // The linkage type (private to the module) - string_constant, // The actual constant value of the string - ".str" // The name of the global variable (used for debugging and identification) + // Allocate space on the stack for the string (including the null terminator) + llvm::AllocaInst *alloca_inst = Builder.CreateAlloca( + llvm::ArrayType::get(llvm::Type::getInt8Ty(Context), strlen(string_node->string) + 1), // +1 for the null terminator + nullptr, // No specific alignment type + "string_alloca" ); - // We use `getGetElementPtr` to get a pointer to the start of the array (the first character) - llvm::Constant *zero = llvm::ConstantInt::get(llvm::Type::getInt32Ty(Context), 0); // The index for the first element of the array - llvm::Constant *indices[] = {zero, zero}; // Indices for the GetElementPtr operation - llvm::Constant *string_ptr = llvm::ConstantExpr::getGetElementPtr( - string_constant->getType(), // The type of the string constant (constant array) - global_string, // The global variable holding the string - indices // The indices to access the first character + // Use `store` to copy the string data into the allocated memory + Builder.CreateStore(string_constant, alloca_inst); + + // Now, we need a pointer to the first character of the string in the stack memory + // We use `CreateGEP` to get the pointer to the start of the array (the first character) + llvm::Value *string_ptr = Builder.CreateGEP( + alloca_inst->getAllocatedType(), // The type of the allocated array + alloca_inst, // The pointer to the allocated memory + {llvm::ConstantInt::get(llvm::Type::getInt32Ty(Context), 0)}, // Index 0 to get the first character + "string_ptr" ); - // This pointer can now be used wherever a pointer to the string is needed in the generated IR + // Add the new string to the symbol table + add_string(string_ptr->getName().str(), string_ptr); + + // Return the pointer to the string return string_ptr; } From 1968ff6a50cb3ab5c47c29c335f1e2e30f70eb15 Mon Sep 17 00:00:00 2001 From: wesuRage Date: Thu, 19 Dec 2024 21:44:51 -0300 Subject: [PATCH 13/21] fix(operator): now operator has the right type --- src/backend/generator/expressions/generate_pre_decrement.cpp | 2 ++ src/backend/generator/expressions/generate_pre_increment.cpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/backend/generator/expressions/generate_pre_decrement.cpp b/src/backend/generator/expressions/generate_pre_decrement.cpp index 382af99..d08c4cf 100644 --- a/src/backend/generator/expressions/generate_pre_decrement.cpp +++ b/src/backend/generator/expressions/generate_pre_decrement.cpp @@ -5,6 +5,8 @@ llvm::Value *generate_pre_decrement(PreDecrementExpr *node, llvm::LLVMContext &C // Generate LLVM IR for the operand (the value to be decremented) llvm::Value *Operand = generate_expr(node->op, Context, Builder, Module); + Operand = Builder.CreatePtrToInt(Operand, llvm::Type::getInt32Ty(Context)); + // Create a subtraction instruction to decrement the operand by 1 // This is a pre-decrement operation, so the operand is decreased before returning the result. llvm::Value *Decremented = Builder.CreateSub(Operand, llvm::ConstantInt::get(llvm::Type::getInt32Ty(Context), 1), "decpretmp"); diff --git a/src/backend/generator/expressions/generate_pre_increment.cpp b/src/backend/generator/expressions/generate_pre_increment.cpp index a387c74..76515f4 100644 --- a/src/backend/generator/expressions/generate_pre_increment.cpp +++ b/src/backend/generator/expressions/generate_pre_increment.cpp @@ -4,6 +4,8 @@ llvm::Value *generate_pre_increment(PreIncrementExpr *node, llvm::LLVMContext &Context, llvm::IRBuilder<> &Builder, llvm::Module &Module) { // Generate LLVM IR for the operand (the value to be incremented) llvm::Value *Operand = generate_expr(node->op, Context, Builder, Module); + + Operand = Builder.CreatePtrToInt(Operand, llvm::Type::getInt32Ty(Context)); // Create an addition instruction to increment the operand by 1 // This is a pre-increment operation, so the operand is increased before returning the result. From bf7487f58086fbfd04c5d3531d4a6ef6b91bbcec Mon Sep 17 00:00:00 2001 From: wesuRage Date: Thu, 19 Dec 2024 21:45:32 -0300 Subject: [PATCH 14/21] feat(global_id_return): keeping track globaly of the return type --- src/backend/generator/expressions/generate_identifier.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backend/generator/expressions/generate_identifier.cpp b/src/backend/generator/expressions/generate_identifier.cpp index f23abf3..bf2e781 100644 --- a/src/backend/generator/expressions/generate_identifier.cpp +++ b/src/backend/generator/expressions/generate_identifier.cpp @@ -4,7 +4,7 @@ llvm::Value *generate_identifier(IdentifierNode *node) { try { - return find_or_wait_for_identifier(node); + return find_or_wait_for_identifier(node, global_id_return); } catch (...) { throw std::runtime_error("Error: identifier not found!"); } From b49a693bc88effd7ba4bad31c84b7b34be821068 Mon Sep 17 00:00:00 2001 From: wesuRage Date: Thu, 19 Dec 2024 21:46:02 -0300 Subject: [PATCH 15/21] feat(string): added string multiplication --- .../expressions/generate_binary_expr.cpp | 51 ++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/src/backend/generator/expressions/generate_binary_expr.cpp b/src/backend/generator/expressions/generate_binary_expr.cpp index 56cc55c..6d58360 100644 --- a/src/backend/generator/expressions/generate_binary_expr.cpp +++ b/src/backend/generator/expressions/generate_binary_expr.cpp @@ -1,6 +1,8 @@ #include "backend/generator/expressions/generate_binary_expr.hpp" #include "backend/generator/expressions/generate_expr.hpp" #include "backend/generator/symbols/identifier_symbol_table.hpp" +#include "backend/generator/symbols/string_symbol_table.hpp" +#include "backend/generator/symbols/function_symbol_table.hpp" llvm::Value *generate_binary_expr(BinaryExprNode *node, llvm::LLVMContext &Context, llvm::IRBuilder<> &Builder, llvm::Module &Module) { llvm::Value *L = generate_expr(node->left, Context, Builder, Module); @@ -16,10 +18,57 @@ llvm::Value *generate_binary_expr(BinaryExprNode *node, llvm::LLVMContext &Conte bool isLPointer = LType->isPointerTy(); bool isRPointer = RType->isPointerTy(); + llvm::errs() << L->getValueName() << "\n"; + llvm::errs() << L->getValueName()->getValue()->getName().str() << "\n"; + if (isLPointer) { + llvm::Value *string = find_string(L->getValueName()->getValue()->getName().str()); + if (string) { + if (isRInteger && strcmp(node->op, "*") == 0) { + auto it = function_symbol_table.find("strrep"); + if (it == function_symbol_table.end()) { + throw std::runtime_error("Function not found in symbol table: strrep"); + } + + llvm::Function *function = it->second; + llvm::FunctionType *func_type = function->getFunctionType(); + + // Prepare arguments for the strrep function + std::vector args; + // The first argument is the string (L) + args.push_back(string); + // The second argument is the repetition count (R) + args.push_back(R); + + // Ensure the types of the arguments are correct + for (size_t i = 0; i < args.size(); ++i) { + llvm::Value *arg = args[i]; + llvm::Type *expected_type = func_type->getParamType(i); + if (arg->getType() != expected_type) { + if (arg->getType()->isIntegerTy() && expected_type->isIntegerTy()) { + 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."); + } + } + args[i] = arg; + } + + // Call the strrep function + llvm::Value *resultBuffer = Builder.CreateCall(function, args); + return resultBuffer; + } + } + const SymbolInfo* symbolInfo = find_identifier(static_cast(node->left->data)->symbol); if (!symbolInfo) { - throw std::runtime_error("Unknown identifier for left operand"); + throw std::runtime_error("Unsupported Left type for binary operation"); } llvm::Type* pointeeType = symbolInfo->type; From 0862203c7a4f9193f2533156a0f8f2434cf55822 Mon Sep 17 00:00:00 2001 From: wesuRage Date: Thu, 19 Dec 2024 21:46:46 -0300 Subject: [PATCH 16/21] feat(global_id_return): getting the right value from it --- src/backend/generator/expressions/generate_call.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/backend/generator/expressions/generate_call.cpp b/src/backend/generator/expressions/generate_call.cpp index 7cead40..35c1bb4 100644 --- a/src/backend/generator/expressions/generate_call.cpp +++ b/src/backend/generator/expressions/generate_call.cpp @@ -1,6 +1,7 @@ #include "backend/generator/expressions/generate_call.hpp" #include "backend/generator/expressions/generate_expr.hpp" #include "backend/generator/symbols/function_symbol_table.hpp" +#include "backend/generator/parallel/queue.hpp" llvm::Value *generate_call(CallNode *call_node, llvm::LLVMContext &Context, llvm::IRBuilder<> &Builder, llvm::Module &Module) { if (!call_node || !call_node->caller) { @@ -23,6 +24,7 @@ llvm::Value *generate_call(CallNode *call_node, llvm::LLVMContext &Context, llvm // Generate arguments std::vector args; for (size_t i = 0; i < call_node->arg_count; ++i) { + global_id_return = "declaration"; llvm::Value *arg = generate_expr(call_node->args[i], Context, Builder, Module); if (!arg) { throw std::runtime_error("Failed to generate call argument."); @@ -47,6 +49,8 @@ llvm::Value *generate_call(CallNode *call_node, llvm::LLVMContext &Context, llvm args.push_back(arg); } + global_id_return = "value"; + // Create the call instruction return Builder.CreateCall(function, args); } From 3cb8bcdfc4e0a9320b6f83a67ef161b5b00cda60 Mon Sep 17 00:00:00 2001 From: wesuRage Date: Thu, 19 Dec 2024 21:47:21 -0300 Subject: [PATCH 17/21] feat(symbols): added declaration to the symbol table --- include/backend/generator/symbols/symbol_stack.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/backend/generator/symbols/symbol_stack.hpp b/include/backend/generator/symbols/symbol_stack.hpp index ec7f94b..e9c8b3e 100644 --- a/include/backend/generator/symbols/symbol_stack.hpp +++ b/include/backend/generator/symbols/symbol_stack.hpp @@ -8,6 +8,7 @@ #include // Include for std::mutex struct SymbolInfo { + llvm::Value* declaration; llvm::Value* value; llvm::Type* type; }; From d830d63786fbe4112f5165146a2013a0117c3491 Mon Sep 17 00:00:00 2001 From: wesuRage Date: Thu, 19 Dec 2024 21:49:29 -0300 Subject: [PATCH 18/21] feat(global_id_return): declaration --- include/backend/generator/parallel/queue.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/backend/generator/parallel/queue.hpp b/include/backend/generator/parallel/queue.hpp index 8288b37..7eb76ce 100644 --- a/include/backend/generator/parallel/queue.hpp +++ b/include/backend/generator/parallel/queue.hpp @@ -19,9 +19,9 @@ struct PendingIdentifier { extern std::mutex symbolTableMutex; extern std::queue pendingQueue; extern std::condition_variable pendingCondition; +extern std::string global_id_return; -llvm::Value* find_or_wait_for_identifier(IdentifierNode *node); - +llvm::Value* find_or_wait_for_identifier(IdentifierNode* node, std::string return_type); void process_pending_identifiers_async(); void process_pending_identifiers_periodically(); From b7e1ce8e2c52fae5348f84943ceee2e0ac9a5be6 Mon Sep 17 00:00:00 2001 From: wesuRage Date: Thu, 19 Dec 2024 21:49:57 -0300 Subject: [PATCH 19/21] misc(dev): tests --- examples/a.glx | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/examples/a.glx b/examples/a.glx index bfc2e91..e59e0cd 100644 --- a/examples/a.glx +++ b/examples/a.glx @@ -1,11 +1,21 @@ -def tigres_de_bengala( int numero) -> int: - int num := numero; - int quatro := num + 1; - return numero ; -end; +extern int write( int, string, int) ; +extern int putchar( int) ; def main( ) -> int: - int num := 3; - int quatro := num + 1; - return tigres_de_bengala( quatro) ; ; + + int linhas := 10; + int colunas := 10; + int chunks := 3; + + for ( int k := 0; k < chunks; ++ k ) : + for ( int i := 0; i < linhas; ++ i ) : + for ( int j := 0; j < colunas; ++ j ) : + int var := write( 1, "a", 1) ; ; + end; + int foo := putchar( 10) ; ; + end; + int bar := putchar( 10) ; ; + end; + + return 0; end; From bb424ae4d4e6fa48676b758f761717c4a614dec9 Mon Sep 17 00:00:00 2001 From: wesuRage Date: Thu, 19 Dec 2024 21:51:50 -0300 Subject: [PATCH 20/21] feat(libs): first LLVM lib for the language's stdlib --- libs/lib.ll | 133 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 libs/lib.ll diff --git a/libs/lib.ll b/libs/lib.ll new file mode 100644 index 0000000..f6ccc75 --- /dev/null +++ b/libs/lib.ll @@ -0,0 +1,133 @@ +@new_line = constant [1 x i8] c"\0A" ; Define a constant representing the newline character (0x0A) + +declare i64 @write(i32, ptr, i64) ; Declare the write syscall, which takes a file descriptor (i32), a pointer to data (ptr), and the length of the data (i64) + +; Implementation of writeln +define i64 @writeln(ptr %str) { +entry: + ; Calculate the length of the string by calling strlen + %len = call i64 @strlen(ptr %str) + + ; Call the write syscall to print the string + call i64 @write(i32 1, ptr %str, i64 %len) ; Write the string to stdout (file descriptor 1) + + ; Get the pointer to the newline character + %newline_ptr = getelementptr [1 x i8], [1 x i8]* @new_line, i64 0, i64 0 + + ; Call the write syscall again to print the newline + %return = call i64 @write(i32 1, ptr %newline_ptr, i64 1) ; Write the newline to stdout + + ret i64 %return ; Return from the writeln function +} + +define i64 @strlen(ptr %input_str) { +entry: + ; Allocate memory to store the starting pointer of the string + %start_ptr = alloca ptr, align 8 + ; Allocate memory to store the current pointer for iteration + %current_ptr = alloca ptr, align 8 + + ; Store the input string pointer in start_ptr + store ptr %input_str, ptr %start_ptr, align 8 + ; Load the initial pointer and store it in current_ptr for iteration + %loaded_start = load ptr, ptr %start_ptr, align 8 + store ptr %loaded_start, ptr %current_ptr, align 8 + + ; Jump to the loop head to start processing the string + br label %loop_head + +loop_head: ; preds = %loop_body, %entry + ; Load the current pointer to get the character it points to + %current_char_ptr = load ptr, ptr %current_ptr, align 8 + ; Load the character at the current pointer + %current_char = load i8, ptr %current_char_ptr, align 1 + ; Check if the character is not the null terminator (0) + %current_char_as_int = sext i8 %current_char to i32 + + %is_not_null = icmp ne i32 %current_char_as_int, 0 + ; If not null, continue the loop; otherwise, exit + br i1 %is_not_null, label %loop_body, label %done + +loop_body: ; preds = %loop_head + ; Load the current pointer + %current_ptr_loaded = load ptr, ptr %current_ptr, align 8 + ; Get the pointer to the next character in the string + %next_char_ptr = getelementptr inbounds i8, ptr %current_ptr_loaded, i32 1 + ; Store the updated pointer back to current_ptr + store ptr %next_char_ptr, ptr %current_ptr, align 8 + ; Go back to the loop head to process the next character + br label %loop_head + +done: ; preds = %loop_head + ; Load the final pointer after reaching the null terminator + %final_ptr = load ptr, ptr %current_ptr, align 8 + ; Load the initial pointer stored in start_ptr + %initial_ptr = load ptr, ptr %start_ptr, align 8 + ; Convert the final pointer to an integer + %final_ptr_as_int = ptrtoint ptr %final_ptr to i64 + ; Convert the initial pointer to an integer + %initial_ptr_as_int = ptrtoint ptr %initial_ptr to i64 + ; Subtract the initial pointer value from the final pointer value to get the string length + %string_length = sub i64 %final_ptr_as_int, %initial_ptr_as_int + ; Return the calculated string length + ret i64 %string_length +} + +@strrep.temp_buffer = internal global [1024 x i8] zeroinitializer, align 16 + +define ptr @strrep(ptr %input_str, i32 %repeat_count) { +entry: + ; Allocate space for intermediate variables + %output_buffer = alloca ptr, align 8 + %string_ptr = alloca ptr, align 8 + %repeat_index = alloca i32, align 4 + %temp_index = alloca i32, align 4 + + ; Initialize variables + store ptr %input_str, ptr %string_ptr, align 8 + store i32 0, ptr %repeat_index, align 4 + store i32 0, ptr %temp_index, align 4 + + br label %check_repeat_loop + +check_repeat_loop: ; Check if repetition loop is complete + %repeat_count_val = load i32, ptr %repeat_index, align 4 + %is_repeat_done = icmp sge i32 %repeat_count_val, %repeat_count + br i1 %is_repeat_done, label %finalize_buffer, label %copy_to_temp_buffer + +copy_to_temp_buffer: ; Copy characters to the buffer + %current_str_ptr = load ptr, ptr %string_ptr, align 8 + %temp_index_val = load i32, ptr %temp_index, align 4 + %char_pos = sext i32 %temp_index_val to i64 + %char_ptr = getelementptr inbounds i8, ptr %current_str_ptr, i64 %char_pos + %char_val = load i8, ptr %char_ptr, align 1 + %is_non_null = icmp ne i8 %char_val, 0 + br i1 %is_non_null, label %continue_copying, label %increment_repeat_index + +continue_copying: ; Copy single character to the temp buffer + %temp_offset = load i32, ptr %temp_index, align 4 + %buffer_pos = getelementptr inbounds [1024 x i8], ptr @strrep.temp_buffer, i64 0, i32 %temp_offset + store i8 %char_val, ptr %buffer_pos, align 1 + %next_index = add nsw i32 %temp_offset, 1 + store i32 %next_index, ptr %temp_index, align 4 + br label %copy_to_temp_buffer + +increment_repeat_index: ; Increment repeat index and reset temp index + %next_repeat = load i32, ptr %repeat_index, align 4 + %incremented_repeat = add i32 %next_repeat, 1 + store i32 %incremented_repeat, ptr %repeat_index, align 4 + store i32 0, ptr %temp_index, align 4 + br label %check_repeat_loop + +finalize_buffer: ; Add null terminator and finalize buffer + %final_size = load i32, ptr %temp_index, align 4 + %final_size64 = sext i32 %final_size to i64 + %final_ptr = getelementptr inbounds [1024 x i8], ptr @strrep.temp_buffer, i64 0, i64 %final_size64 + store i8 0, ptr %final_ptr, align 1 + store ptr @strrep.temp_buffer, ptr %output_buffer, align 8 + br label %return_buffer + +return_buffer: ; Return the buffer + %final_output = load ptr, ptr %output_buffer, align 8 + ret ptr %final_output +} From 7136447e52b92a5c97d7bb67257b08e9cb0ace7e Mon Sep 17 00:00:00 2001 From: wesuRage Date: Thu, 19 Dec 2024 21:52:16 -0300 Subject: [PATCH 21/21] fix(LLVM): included *.ll --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index f3a236c..c9b4e05 100644 --- a/.gitignore +++ b/.gitignore @@ -4,7 +4,6 @@ *_test *_main *.tree -*.ll .idea/ .vscode/ gdb.txt