Stage-A selfhost emitter fixes and LLVM opt toggle
This commit is contained in:
@ -41,6 +41,42 @@ from build_ctx import BuildCtx
|
||||
from resolver import Resolver
|
||||
from mir_reader import MIRReader
|
||||
|
||||
_OPT_ENV_KEYS = ("HAKO_LLVM_OPT_LEVEL", "NYASH_LLVM_OPT_LEVEL")
|
||||
|
||||
def _parse_opt_level_env() -> int:
|
||||
"""Return desired optimization level (0-3). Defaults to 2."""
|
||||
for key in _OPT_ENV_KEYS:
|
||||
raw = os.environ.get(key)
|
||||
if not raw:
|
||||
continue
|
||||
value = raw.strip()
|
||||
if not value:
|
||||
continue
|
||||
upper = value.upper()
|
||||
if upper.startswith("O"):
|
||||
value = upper[1:]
|
||||
try:
|
||||
lvl = int(value)
|
||||
except ValueError:
|
||||
continue
|
||||
if lvl < 0:
|
||||
lvl = 0
|
||||
if lvl > 3:
|
||||
lvl = 3
|
||||
return lvl
|
||||
return 2
|
||||
|
||||
def _resolve_codegen_opt_level():
|
||||
"""Map env level to llvmlite CodeGenOptLevel enum (fallback to int)."""
|
||||
level = _parse_opt_level_env()
|
||||
try:
|
||||
names = {0: "None", 1: "Less", 2: "Default", 3: "Aggressive"}
|
||||
enum = getattr(llvm, "CodeGenOptLevel")
|
||||
attr = names.get(level, "Default")
|
||||
return getattr(enum, attr)
|
||||
except Exception:
|
||||
return level
|
||||
|
||||
class NyashLLVMBuilder:
|
||||
"""Main LLVM IR builder for Nyash MIR"""
|
||||
|
||||
@ -627,7 +663,11 @@ class NyashLLVMBuilder:
|
||||
"""Compile module to object file"""
|
||||
# Create target machine
|
||||
target = llvm.Target.from_default_triple()
|
||||
target_machine = target.create_target_machine()
|
||||
target_machine = target.create_target_machine(opt=_resolve_codegen_opt_level())
|
||||
try:
|
||||
trace_debug(f"[Python LLVM] opt-level={_parse_opt_level_env()}")
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Compile
|
||||
ir_text = str(self.module)
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
use super::{ConstValue, MirInstruction, ValueId};
|
||||
use crate::ast::ASTNode;
|
||||
use crate::mir::slot_registry::{get_or_assign_type_id, reserve_method_slot};
|
||||
use serde_json;
|
||||
use std::collections::HashSet;
|
||||
|
||||
impl super::MirBuilder {
|
||||
@ -27,17 +28,18 @@ impl super::MirBuilder {
|
||||
self.current_static_box = Some(box_name.clone());
|
||||
// Look for the main() method
|
||||
let out = if let Some(main_method) = methods.get("main") {
|
||||
if let ASTNode::FunctionDeclaration { params, body, .. } = main_method {
|
||||
// Also materialize a callable function entry "BoxName.main/N" for harness/PyVM
|
||||
let func_name = format!("{}.{}", box_name, "main");
|
||||
let _ = self.lower_static_method_as_function(func_name, params.clone(), body.clone());
|
||||
// Convert the method body to a Program AST node and lower it
|
||||
let program_ast = ASTNode::Program {
|
||||
if let ASTNode::FunctionDeclaration { params, body, .. } = main_method {
|
||||
// Also materialize a callable function entry "BoxName.main/N" for harness/PyVM
|
||||
let func_name = format!("{}.{}", box_name, "main");
|
||||
let _ = self.lower_static_method_as_function(func_name, params.clone(), body.clone());
|
||||
// Convert the method body to a Program AST node and lower it
|
||||
let program_ast = ASTNode::Program {
|
||||
statements: body.clone(),
|
||||
span: crate::ast::Span::unknown(),
|
||||
};
|
||||
// Bind default parameters if present (e.g., args=[])
|
||||
let saved_var_map = std::mem::take(&mut self.variable_map);
|
||||
let script_args = collect_script_args_from_env();
|
||||
for p in params.iter() {
|
||||
let pid = self.value_gen.next();
|
||||
if p == "args" {
|
||||
@ -47,6 +49,24 @@ impl super::MirBuilder {
|
||||
box_type: "ArrayBox".to_string(),
|
||||
args: vec![],
|
||||
})?;
|
||||
self.value_origin_newbox
|
||||
.insert(pid, "ArrayBox".to_string());
|
||||
self
|
||||
.value_types
|
||||
.insert(pid, super::MirType::Box("ArrayBox".to_string()));
|
||||
if let Some(args) = script_args.as_ref() {
|
||||
for arg in args {
|
||||
let val = crate::mir::builder::emission::constant::emit_string(self, arg.clone());
|
||||
self.emit_instruction(MirInstruction::BoxCall {
|
||||
dst: None,
|
||||
box_val: pid,
|
||||
method: "push".to_string(),
|
||||
method_id: None,
|
||||
args: vec![val],
|
||||
effects: super::EffectMask::MUT,
|
||||
})?;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let v = crate::mir::builder::emission::constant::emit_void(self);
|
||||
// ensure pid holds the emitted const id
|
||||
@ -137,3 +157,13 @@ impl super::MirBuilder {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn collect_script_args_from_env() -> Option<Vec<String>> {
|
||||
let raw = std::env::var("NYASH_SCRIPT_ARGS_JSON")
|
||||
.or_else(|_| std::env::var("HAKO_SCRIPT_ARGS_JSON"))
|
||||
.ok()?;
|
||||
match serde_json::from_str::<Vec<String>>(&raw) {
|
||||
Ok(list) if !list.is_empty() => Some(list),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user