Skip to content

Commit

Permalink
IFs Generation and FOR corrections (#72 from wesuRage/main)
Browse files Browse the repository at this point in the history
IFs Generation and FOR corrections
  • Loading branch information
wesuRage authored Jan 11, 2025
2 parents 2bc9c05 + e226d68 commit 94c0001
Show file tree
Hide file tree
Showing 16 changed files with 337 additions and 58 deletions.
16 changes: 8 additions & 8 deletions examples/a.glx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
extern int writeln( string) ;
extern string itos( int) ;
extern int writeln(string);
extern string itos(int);

def main( ) -> int:
def main() -> int:

for ( int i := 0; i < 100000; ++ i) :
writeln( "val" ) ;
end;
for (int i := -10; i < 10 + 1; ++i):
writeln(itos(i););
end;

return 0;
end;
return 0;
end;
16 changes: 16 additions & 0 deletions include/backend/generator/statements/generate_if_stmt.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#ifndef GENERATE_IF_STMT_H
#define GENERATE_IF_STMT_H

extern "C" {
#include "frontend/ast/definitions.h"
}
#include <llvm/IR/IRBuilder.h>
#include <llvm/IR/Function.h>
#include <llvm/IR/Type.h>
#include <llvm/IR/Value.h>
#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/BasicBlock.h>

llvm::Value* generate_if_stmt(IfNode *node, llvm::LLVMContext &Context, llvm::IRBuilder<> &Builder, llvm::Module &Module);

#endif // GENERATE_IF_STMT_H
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#include <llvm/IR/Function.h>
#include "backend/generator/symbols/symbol_stack.hpp"

const SymbolInfo *find_identifier(const std::string &name);
SymbolInfo *find_identifier(const std::string &name);
void add_identifier(const std::string &name, llvm::Value* declaration, llvm::Value* value, llvm::Type* type);

#endif // IDENTIFIER_SYMBOL_TABLE_H
22 changes: 22 additions & 0 deletions include/backend/generator/symbols/iterator_stack.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#ifndef ITERATOR_STACK_H
#define ITERATOR_STACK_H

#include <stack>
#include <string>
#include <llvm/IR/Value.h>
#include <mutex>

struct IteratorInfo {
llvm::Value* declaration;
llvm::Value* value;
llvm::Type* type;
};

extern std::stack<IteratorInfo> iterator_stack;
extern std::mutex iterator_stack_mutex;

void push_iterator(llvm::Value* declaration, llvm::Value* value, llvm::Type* type);
IteratorInfo pop_iterator();
IteratorInfo* current_iterator();

#endif // ITERATOR_STACK_H
116 changes: 116 additions & 0 deletions libs/lib.ll
Original file line number Diff line number Diff line change
Expand Up @@ -309,3 +309,119 @@ exit: ; preds = %finalize, %abort
; Return the pointer to the repeated string (or null if aborted).
}

declare ptr @malloc(i64)


define ptr @itos(i32 %num) {
entry:
; Alocação de variáveis
%is_negative = alloca i1
%num_ptr = alloca i32
%buffer = alloca ptr
%i = alloca i32

; Inicializa variáveis
store i32 %num, ptr %num_ptr
store i1 0, ptr %is_negative

; Aloca buffer dinâmico para a string (máximo 12 bytes: "-2147483648" + '\0')
%buf = call ptr @malloc(i64 12)
store ptr %buf, ptr %buffer
store i32 0, ptr %i

; Verifica se o número é negativo
%num_val = load i32, ptr %num_ptr
%is_neg = icmp slt i32 %num_val, 0
br i1 %is_neg, label %negative, label %positive

negative: ; Bloco para números negativos
store i1 1, ptr %is_negative
%neg_num = sub i32 0, %num_val
store i32 %neg_num, ptr %num_ptr
br label %extract_digits

positive: ; Continua o processamento
br label %extract_digits

extract_digits: ; Extrai os dígitos
%num_val2 = load i32, ptr %num_ptr
%digit = urem i32 %num_val2, 10
%char_digit = add i32 %digit, 48 ; Converte para caractere
%i_val = load i32, ptr %i
%buf_ptr = load ptr, ptr %buffer
%str_loc = getelementptr i8, ptr %buf_ptr, i32 %i_val
store i32 %char_digit, ptr %str_loc

; Atualiza número e índice
%next_num = sdiv i32 %num_val2, 10
store i32 %next_num, ptr %num_ptr
%next_i = add i32 %i_val, 1
store i32 %next_i, ptr %i

; Verifica se o número é maior que zero
%is_not_zero = icmp ne i32 %next_num, 0
br i1 %is_not_zero, label %extract_digits, label %check_negative

check_negative: ; Adiciona o sinal de menos se necessário
%is_neg2 = load i1, ptr %is_negative
br i1 %is_neg2, label %add_minus, label %reverse_buffer

add_minus: ; Adiciona o sinal de menos
%i_val2 = load i32, ptr %i
%buf_ptr2 = load ptr, ptr %buffer
%str_loc2 = getelementptr i8, ptr %buf_ptr2, i32 %i_val2
store i8 45, ptr %str_loc2 ; '-' é 45 na tabela ASCII
%next_i2 = add i32 %i_val2, 1
store i32 %next_i2, ptr %i
br label %reverse_buffer

reverse_buffer: ; Reverte o buffer
%buf_ptr3 = load ptr, ptr %buffer
%len = load i32, ptr %i

; Índices para reversão
%start = alloca i32
%end = alloca i32
store i32 0, ptr %start
%end_idx = sub i32 %len, 1
store i32 %end_idx, ptr %end

br label %reverse_loop

reverse_loop: ; Loop para inverter os caracteres
%start_idx = load i32, ptr %start
%end_idx_initial = load i32, ptr %end
%cmp = icmp slt i32 %start_idx, %end_idx_initial
br i1 %cmp, label %swap_chars, label %finalize_string

swap_chars: ; Troca os caracteres
%buf_ptr4 = load ptr, ptr %buffer

; Posições dos caracteres
%start_char_ptr = getelementptr i8, ptr %buf_ptr4, i32 %start_idx
%end_char_ptr = getelementptr i8, ptr %buf_ptr4, i32 %end_idx

; Carrega os valores
%start_char = load i8, ptr %start_char_ptr
%end_char = load i8, ptr %end_char_ptr

; Troca os valores
store i8 %end_char, ptr %start_char_ptr
store i8 %start_char, ptr %end_char_ptr

; Atualiza os índices
%next_start = add i32 %start_idx, 1
%prev_end = sub i32 %end_idx, 1
store i32 %next_start, ptr %start
store i32 %prev_end, ptr %end

br label %reverse_loop

finalize_string: ; Finaliza a string
%i_val3 = load i32, ptr %i
%buf_ptr5 = load ptr, ptr %buffer
%str_loc3 = getelementptr i8, ptr %buf_ptr5, i32 %i_val3
store i8 0, ptr %str_loc3 ; Terminador nulo
%final_buf = load ptr, ptr %buffer
ret ptr %final_buf
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@ llvm::Value *generate_assignment_expr(AssignmentNode *node, llvm::LLVMContext &C
// right-hand side to the memory location of the left-hand side.
Builder.CreateStore(right_value, left_value);

// Return a null value of the type of the left operand,
// as assignment expressions generally do not return a value.
return llvm::Constant::getNullValue(left_value->getType());
return left_value;
}

71 changes: 51 additions & 20 deletions src/backend/generator/expressions/generate_call.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
#include "backend/generator/expressions/generate_expr.hpp"
#include "backend/generator/symbols/function_symbol_table.hpp"
#include "backend/generator/utils/return_id.hpp"
#include "backend/generator/parallel/queue.hpp"
#include "backend/generator/symbols/iterator_stack.hpp"
#include <iostream>

llvm::Value *generate_call(CallNode *call_node, llvm::LLVMContext &Context, llvm::IRBuilder<> &Builder, llvm::Module &Module) {
if (!call_node || !call_node->caller) {
Expand All @@ -24,33 +27,61 @@ llvm::Value *generate_call(CallNode *call_node, llvm::LLVMContext &Context, llvm
// Generate arguments
std::vector<llvm::Value *> 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);
global_id_return = "value";

// Declare expected_type here before using it
llvm::Type* expected_type = func_type->getParamType(i);

// Get the current iterator info
IteratorInfo* current_iter = current_iterator();
llvm::Value *arg = nullptr;

if (current_iter) {
// Get the current argument as an IdentifierNode
IdentifierNode* arg_identifier = static_cast<IdentifierNode*>(call_node->args[i]->data);
if (arg_identifier && current_iter->value && current_iter->value->getName().str() == arg_identifier->symbol) {
// If the current iterator matches the argument name, use the current iterator data
arg = current_iter->value;
expected_type = current_iter->type; // Override expected_type with current iterator's type
}
}


if (!arg) {
throw std::runtime_error("Failed to generate call argument.");
// Otherwise, generate the argument value as usual
global_id_return = "declaration";
arg = generate_expr(call_node->args[i], Context, Builder, Module);
if (!arg) {
throw std::runtime_error("Failed to generate call argument.");
}
}

// Ensure the argument type matches the function parameter type
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);
llvm::errs() << *arg << "\n";
// Check if the argument is a pointer
if (arg->getType()->isPointerTy()) {
if (expected_type->isPointerTy()) {
args.push_back(arg);
} else {
throw std::runtime_error("Argument type mismatch.");
llvm::Value *loaded_value = Builder.CreateLoad(expected_type, arg);
args.push_back(loaded_value);
}
} else {
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()->isIntegerTy() && expected_type->isFloatingPointTy()) {
arg = Builder.CreateSIToFP(arg, expected_type);
} else if (arg->getType()->isFloatingPointTy() && expected_type->isIntegerTy()) {
arg = Builder.CreateFPToSI(arg, expected_type);
} else {
throw std::runtime_error("Argument type mismatch.");
}
}
args.push_back(arg);
}

args.push_back(arg);
}

global_id_return = "value";

// Create the call instruction
return Builder.CreateCall(function, args);
}
4 changes: 3 additions & 1 deletion src/backend/generator/expressions/generate_identifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,7 @@ llvm::Value *generate_identifier(IdentifierNode *node) {
} else {
return id->value;
}
} else {
throw std::runtime_error("Identifier not found: " + std::string(node->symbol));
}
}
}
2 changes: 1 addition & 1 deletion src/backend/generator/expressions/generate_unary_minus.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ llvm::Value *generate_unary_minus(UnaryMinusExpr *node, llvm::LLVMContext &Conte
llvm::Value *Operand = generate_expr(node->op, Context, Builder, Module);

// Create a floating-point negation instruction, which negates the operand (i.e., multiplies it by -1)
llvm::Value *Negated = Builder.CreateFNeg(Operand, "negtmp");
llvm::Value *Negated = Builder.CreateNeg(Operand, "negtmp");

// Return the result of the negation
return Negated;
Expand Down
Loading

0 comments on commit 94c0001

Please sign in to comment.