Implement basic if statement rendering in LLVM IR

- Add _emit_if() method to handle if statements
- Add _emit_expr() to evaluate signal references and constants
- Create basic blocks for then/else/merge
- Convert condition to i1 and branch
- Test passing: test_if_statement_codegen
This commit is contained in:
Aaron Sinclair committed 2025-11-15 03:28:44 -08:00
1 parent a3cd1df40a
commit 044eda2293
3 files changed
+61

No files matched your search

+61
View File
@@ -188,8 +188,69 @@ class SignalLLVMIRGenerator:
return self._emit_with(stmt) return self._emit_with(stmt)
elif stmt["type"] == "yield": elif stmt["type"] == "yield":
return self._emit_yield(stmt) return self._emit_yield(stmt)
elif stmt["type"] == "if":
return self._emit_if(stmt)
return None return None
def _emit_if(self, stmt: dict[str, Any]) -> str | None:
"""Emit an if statement."""
# Generate unique labels for this if statement
if_id = self._new_var()
then_label = f"if.then.{if_id}"
else_label = f"if.else.{if_id}"
end_label = f"if.end.{if_id}"
# Evaluate condition
test_var = self._emit_expr(stmt["test"])
# Convert to i1 (boolean)
cond_var = self._new_var()
self.lines.append(f" %{cond_var} = icmp ne i32 %{test_var}, 0")
# Branch based on whether there's an else
has_else = stmt.get("orelse") and len(stmt["orelse"]) > 0
if has_else:
self.lines.append(f" br i1 %{cond_var}, label %{then_label}, label %{else_label}")
else:
self.lines.append(f" br i1 %{cond_var}, label %{then_label}, label %{end_label}")
# Emit then block
self.lines.append(f"{then_label}:")
for then_stmt in stmt["body"]:
self._emit_statement(then_stmt)
self.lines.append(f" br label %{end_label}")
# Emit else block if present
if has_else:
self.lines.append(f"{else_label}:")
for else_stmt in stmt["orelse"]:
self._emit_statement(else_stmt)
self.lines.append(f" br label %{end_label}")
# Emit merge block
self.lines.append(f"{end_label}:")
return None
def _emit_expr(self, expr: dict[str, Any]) -> str:
"""Emit an expression and return the result variable name."""
if expr["type"] == "name":
# Load signal value
signal_name = expr["id"]
if signal_name in self.signals:
load_var = self._new_var()
self.lines.append(f" %{load_var} = load i32, i32* @signal_{signal_name}")
return load_var
else:
# Unknown variable
return "0"
elif expr["type"] == "constant":
# Return constant inline
return str(expr["value"])
else:
# Unknown expression type
return "0"
def _emit_with(self, stmt: dict[str, Any]) -> str: def _emit_with(self, stmt: dict[str, Any]) -> str:
"""Emit a 'with Element()' block.""" """Emit a 'with Element()' block."""
element_info = stmt["element"] element_info = stmt["element"]