Skip to content

Support for string type #36

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 57 additions & 9 deletions src/irx/builders/llvmliteir.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ class VariablesLLVM:
INT8_TYPE: ir.types.Type
INT32_TYPE: ir.types.Type
VOID_TYPE: ir.types.Type
STRING_TYPE: ir.types.Type
STRING_PTR_TYPE: ir.types.Type # Add pointer type for strings

context: ir.context.Context
module: ir.module.Module
Expand Down Expand Up @@ -73,6 +75,8 @@ def get_data_type(self, type_name: str) -> ir.types.Type:
return self.INT8_TYPE
elif type_name == "void":
return self.VOID_TYPE
elif type_name == "string":
return self.STRING_TYPE

raise Exception("[EE]: type_name not valid.")

Expand Down Expand Up @@ -197,9 +201,14 @@ def create_entry_block_alloca(
self._llvm.ir_builder.position_at_start(
self._llvm.ir_builder.function.entry_basic_block
)
alloca = self._llvm.ir_builder.alloca(
self._llvm.get_data_type(type_name), None, var_name
)
if type_name == "string":
alloca = self._llvm.ir_builder.alloca(
ir.PointerType(self._llvm.STRING_TYPE), None, var_name
)
else:
alloca = self._llvm.ir_builder.alloca(
self._llvm.get_data_type(type_name), None, var_name
)
self._llvm.ir_builder.position_at_end(self._llvm.ir_builder.block)
return alloca

Expand Down Expand Up @@ -604,6 +613,27 @@ def visit(self, expr: astx.LiteralInt32) -> None:
result = ir.Constant(self._llvm.INT32_TYPE, expr.value)
self.result_stack.append(result)

@dispatch # type: ignore[no-redef]
def visit(self, expr: astx.LiteralString) -> None:
"""Translate ASTx LiteralString to LLVM-IR."""
# Create a global string constant
global_string = ir.GlobalVariable(
self._llvm.module, self._llvm.STRING_TYPE, name="str"
)
global_string.initializer = ir.Constant(
ir.ArrayType(ir.IntType(8), len(expr.value)),
bytearray(expr.value, "utf-8"),
)
global_string.linkage = "internal"
global_string.global_constant = True

# Get a pointer to the first element of the string
zero = ir.Constant(ir.IntType(32), 0)
gep = self._llvm.ir_builder.gep(
global_string, [zero, zero], name="strptr"
)
self.result_stack.append(gep)

@dispatch # type: ignore[no-redef]
def visit(self, expr: astx.FunctionCall) -> None:
"""Translate Function FunctionCall."""
Expand Down Expand Up @@ -658,9 +688,15 @@ def visit(self, expr: astx.Function) -> None:
@dispatch # type: ignore[no-redef]
def visit(self, expr: astx.FunctionPrototype) -> None:
"""Translate ASTx Function Prototype to LLVM-IR."""
args_type = [self._llvm.INT32_TYPE] * len(expr.args.nodes)
# note: it should be dynamic
return_type = self._llvm.get_data_type("int32")
args_type = []
for arg in expr.args.nodes:
if arg.type == "string":
args_type.append(ir.PointerType(self._llvm.STRING_TYPE))
else:
# args_type.append(self._llvm.get_data_type(arg.type))
args_type.append(self._llvm.INT32_TYPE)

return_type = self._llvm.get_data_type(expr.return_type)
fn_type = ir.FunctionType(return_type, args_type, False)

fn = ir.Function(self._llvm.module, fn_type, expr.name)
Expand Down Expand Up @@ -698,9 +734,17 @@ def visit(self, expr: astx.InlineVariableDeclaration) -> None:
init_val = self.result_stack.pop()
if init_val is None:
raise Exception("Initializer code generation failed.")
elif expr.type == "string":
# Initialize an empty string
init_val = ir.Constant(
ir.ArrayType(ir.IntType(8), 0), bytearray("", "utf-8")
)
else:
# Default to INT32 and initialize to 0
init_val = ir.Constant(self._llvm.get_data_type("int32"), 0)

# Create an alloca in the entry block.
alloca = self.create_entry_block_alloca(expr.name, expr.type)
alloca = self.create_entry_block_alloca(expr.name, "int32")
self._llvm.ir_builder.store(init_val, alloca)
self.named_values[expr.name] = alloca
Expand Down Expand Up @@ -730,10 +774,14 @@ def visit(self, expr: astx.VariableDeclaration) -> None:
init_val = self.result_stack.pop()
if init_val is None:
raise Exception("Initializer code generation failed.")
# If not specified, use 0 as the initializer.
# note: it should create something according to the defined type
elif expr.type == "string":
init_val = ir.Constant(
ir.ArrayType(ir.IntType(8), 0), bytearray("", "utf-8")
)
else:
# If not specified, use 0 as the initializer.
# note: it should create something according to the defined type
init_val = ir.Constant(self._llvm.get_data_type("int32"), 0)
init_val = ir.Constant(self._llvm.get_data_type(expr.type), 0)

# Create an alloca in the entry block.
# note: it should create the type according to the defined type
Expand Down
Loading