Skip to content

Commit

Permalink
Implementing ftos & power operation (#74 from wesuRage/main)
Browse files Browse the repository at this point in the history
Implementing `ftos` & power operation
  • Loading branch information
wesuRage authored Jan 13, 2025
2 parents 13bb6c9 + be5ba4a commit de3ff26
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 50 deletions.
101 changes: 59 additions & 42 deletions libs/lib.ll
Original file line number Diff line number Diff line change
Expand Up @@ -311,95 +311,94 @@ exit: ; preds = %finalize, %abort

declare ptr @malloc(i64)


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

; Inicializa variáveis
store i32 %num, ptr %num_ptr
store i64 %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
store i64 0, ptr %i

; Verifica se o número é negativo
%num_val = load i32, ptr %num_ptr
%is_neg = icmp slt i32 %num_val, 0
%num_val = load i64, ptr %num_ptr
%is_neg = icmp slt i64 %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
%neg_num = sub i64 0, %num_val
store i64 %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
%num_val2 = load i64, ptr %num_ptr
%digit = urem i64 %num_val2, 10
%char_digit = add i64 %digit, 48 ; Converte para caractere
%i_val = load i64, 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
%str_loc = getelementptr i8, ptr %buf_ptr, i64 %i_val
store i64 %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
%next_num = sdiv i64 %num_val2, 10
store i64 %next_num, ptr %num_ptr
%next_i = add i64 %i_val, 1
store i64 %next_i, ptr %i

; Verifica se o número é maior que zero
%is_not_zero = icmp ne i32 %next_num, 0
%is_not_zero = icmp ne i64 %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
%i_val2 = load i64, ptr %i
%buf_ptr2 = load ptr, ptr %buffer
%str_loc2 = getelementptr i8, ptr %buf_ptr2, i32 %i_val2
%str_loc2 = getelementptr i8, ptr %buf_ptr2, i64 %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
%next_i2 = add i64 %i_val2, 1
store i64 %next_i2, ptr %i
br label %reverse_buffer

reverse_buffer: ; Reverte o buffer
%buf_ptr3 = load ptr, ptr %buffer
%len = load i32, ptr %i
%len = load i64, 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
%start = alloca i64
%end = alloca i64
store i64 0, ptr %start
%end_idx = sub i64 %len, 1
store i64 %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
%start_idx = load i64, ptr %start
%end_idx_initial = load i64, ptr %end
%cmp = icmp slt i64 %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
%start_char_ptr = getelementptr i8, ptr %buf_ptr4, i64 %start_idx
%end_char_ptr = getelementptr i8, ptr %buf_ptr4, i64 %end_idx

; Carrega os valores
%start_char = load i8, ptr %start_char_ptr
Expand All @@ -410,18 +409,36 @@ swap_chars: ; Troca os caracteres
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
%next_start = add i64 %start_idx, 1
%prev_end = sub i64 %end_idx, 1
store i64 %next_start, ptr %start
store i64 %prev_end, ptr %end

br label %reverse_loop

finalize_string: ; Finaliza a string
%i_val3 = load i32, ptr %i
%i_val3 = load i64, ptr %i
%buf_ptr5 = load ptr, ptr %buffer
%str_loc3 = getelementptr i8, ptr %buf_ptr5, i32 %i_val3
%str_loc3 = getelementptr i8, ptr %buf_ptr5, i64 %i_val3
store i8 0, ptr %str_loc3 ; Terminador nulo
%final_buf = load ptr, ptr %buffer
ret ptr %final_buf
}

declare i32 @sprintf(ptr %buffer, ptr %format, ...) #1

define ptr @ftos(double %x) {
entry:
; Aloca espaço para o buffer de resultado
%buffer = alloca [128 x i8], align 1

; Define a constante local para o formato "%f"
%format = alloca [4 x i8], align 1
store [3 x i8] c"%f\00", ptr %format

; Chama o sprintf com a string de formato
call i32 @sprintf(ptr %buffer, ptr %format, double %x)

; Retorna o resultado final (buffer) com a string
ret ptr %buffer
}
20 changes: 17 additions & 3 deletions src/backend/generator/expressions/generate_binary_expr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#include "backend/generator/symbols/identifier_symbol_table.hpp"
#include "backend/generator/symbols/string_symbol_table.hpp"
#include "backend/generator/symbols/function_symbol_table.hpp"
#include <iostream>
#include <cmath>

llvm::Value *generate_binary_expr(BinaryExprNode *node, llvm::LLVMContext &Context, llvm::IRBuilder<llvm::NoFolder> &Builder, llvm::Module &Module) {
llvm::Value *L = generate_expr(node->left, Context, Builder, Module);
Expand Down Expand Up @@ -63,8 +63,6 @@ llvm::Value *generate_binary_expr(BinaryExprNode *node, llvm::LLVMContext &Conte
return resultBuffer;
}
} else {

llvm::errs() << "Value: " << L->getValueName()->getValue()->getName().str() << "\n";
const SymbolInfo* symbolInfo;

symbolInfo = find_identifier(static_cast<IdentifierNode*>(node->left->data)->symbol);
Expand Down Expand Up @@ -118,6 +116,18 @@ llvm::Value *generate_binary_expr(BinaryExprNode *node, llvm::LLVMContext &Conte
if (strcmp(node->op, "^") == 0) return Builder.CreateXor(L, R, "xortmp");
if (strcmp(node->op, ">>") == 0) return Builder.CreateAShr(L, R, "shrtmp");
if (strcmp(node->op, "<<") == 0) return Builder.CreateShl(L, R, "shltmp");
if (strcmp(node->op, "**") == 0) {
if (L->getType()->isIntegerTy()) {
L = Builder.CreateSIToFP(L, llvm::Type::getDoubleTy(Context), "cast_to_fp_L");
}
if (R->getType()->isIntegerTy()) {
R = Builder.CreateSIToFP(R, llvm::Type::getDoubleTy(Context), "cast_to_fp_R");
}

llvm::Function *powFunction = llvm::Intrinsic::getDeclaration(&Module, llvm::Intrinsic::pow, { L->getType() });
return Builder.CreateCall(powFunction, { L, R }, "powtmp");
}


if (strcmp(node->op, "==") == 0) return Builder.CreateICmpEQ(L, R, "eqtmp");
if (strcmp(node->op, "!=") == 0) return Builder.CreateICmpNE(L, R, "netmp");
Expand All @@ -141,6 +151,10 @@ llvm::Value *generate_binary_expr(BinaryExprNode *node, llvm::LLVMContext &Conte
if (strcmp(node->op, "-") == 0) return Builder.CreateFSub(L, R, "subtmp");
if (strcmp(node->op, "*") == 0) return Builder.CreateFMul(L, R, "multmp");
if (strcmp(node->op, "/") == 0) return Builder.CreateFDiv(L, R, "divtmp");
if (strcmp(node->op, "**") == 0) {
llvm::Function *powFunction = llvm::Intrinsic::getDeclaration(&Module, llvm::Intrinsic::pow, { L->getType() });
return Builder.CreateCall(powFunction, { L, R }, "powtmp");
}

if (strcmp(node->op, "==") == 0) return Builder.CreateFCmpOEQ(L, R, "eqtmp");
if (strcmp(node->op, "!=") == 0) return Builder.CreateFCmpONE(L, R, "netmp");
Expand Down
10 changes: 5 additions & 5 deletions src/backend/generator/expressions/generate_unary_minus.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ llvm::Value *generate_unary_minus(UnaryMinusExpr *node, llvm::LLVMContext &Conte
// Generate LLVM IR for the operand (the value to apply the unary minus operation on)
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.CreateNeg(Operand, "negtmp");

// Return the result of the negation
return Negated;
if (Operand->getType()->isDoubleTy()) {
return Builder.CreateFNeg(Operand, "negtmp");
} else {
return Builder.CreateNeg(Operand, "negtmp");
}
}

0 comments on commit de3ff26

Please sign in to comment.