Phase 22.x WIP: LLVM backend improvements + MIR builder enhancements
LLVM backend improvements: - Add native LLVM backend support (NYASH_LLVM_BACKEND=native) - Add crate backend selector with priority (crate > llvmlite) - Add native_llvm_builder.py for native IR generation - Add NYASH_LLVM_NATIVE_TRACE=1 for IR dump MIR builder enhancements: - Refactor lower_if_compare_* boxes for better code generation - Refactor lower_return_* boxes for optimized returns - Refactor lower_loop_* boxes for loop handling - Refactor lower_method_* boxes for method calls - Update pattern_util_box for better pattern matching Smoke tests: - Add phase2100 S3 backend selector tests (17 new tests) - Add phase2120 native backend tests (4 new tests) - Add phase2034 MIR builder internal tests (2 new tests) - Add phase2211 TLV shim parity test Documentation: - Update ENV_VARS.md with LLVM backend variables - Update CURRENT_TASK.md with progress - Update README.md and CHANGELOG.md Config: - Add NYASH_LLVM_BACKEND env support in src/config/env.rs - Update ny_mir_builder.sh for backend selection - Update dispatch.rs for backend routing Tools: - Add tools/native_llvm_builder.py - Update smokes/v2/profiles/quick/core/phase2100/run_all.sh Known: Many Hako builder internal files modified for optimization
This commit is contained in:
@ -33,9 +33,12 @@ impl NyashEnv {
|
||||
|
||||
// Global current env config (thread-safe)
|
||||
use once_cell::sync::OnceCell;
|
||||
use std::collections::HashSet;
|
||||
use std::sync::Mutex;
|
||||
use std::sync::RwLock;
|
||||
|
||||
static GLOBAL_ENV: OnceCell<RwLock<NyashEnv>> = OnceCell::new();
|
||||
static WARNED_ALIASES: OnceCell<Mutex<HashSet<String>>> = OnceCell::new();
|
||||
// フェーズM.2: PHI_ON_GATED_WARNED削除(phi-legacy簡略化により不要)
|
||||
|
||||
pub fn current() -> NyashEnv {
|
||||
@ -376,11 +379,19 @@ pub fn cli_verbose() -> bool {
|
||||
}
|
||||
pub fn enable_using() -> bool {
|
||||
// Phase 15: デフォルトON(using systemはメイン機能)
|
||||
// NYASH_ENABLE_USING=0 で明示的に無効化可能
|
||||
// NYASH_ENABLE_USING=0 で明示的に無効化可能。HAKO_ENABLE_USING は互換のため受理(警告)。
|
||||
match std::env::var("NYASH_ENABLE_USING").ok().as_deref() {
|
||||
Some("0") | Some("false") | Some("off") => false,
|
||||
_ => true, // デフォルト: ON
|
||||
Some("0") | Some("false") | Some("off") => return false,
|
||||
Some(_) => return true,
|
||||
None => {}
|
||||
}
|
||||
// Fallback to alias
|
||||
if let Some(v) = std::env::var("HAKO_ENABLE_USING").ok() {
|
||||
warn_alias_once("HAKO_ENABLE_USING", "NYASH_ENABLE_USING");
|
||||
let lv = v.to_ascii_lowercase();
|
||||
return !(lv == "0" || lv == "false" || lv == "off");
|
||||
}
|
||||
true // default ON
|
||||
}
|
||||
|
||||
// ---- Using profiles (dev|ci|prod) ----
|
||||
@ -466,7 +477,14 @@ pub fn ny_compiler_stage3() -> bool {
|
||||
/// When enabled, the Rust parser accepts Stage-3 surface (try/catch/finally, throw).
|
||||
/// Default is OFF to keep Stage-2 stable.
|
||||
pub fn parser_stage3() -> bool {
|
||||
std::env::var("NYASH_PARSER_STAGE3").ok().as_deref() == Some("1")
|
||||
if std::env::var("NYASH_PARSER_STAGE3").ok().as_deref() == Some("1") {
|
||||
return true;
|
||||
}
|
||||
if std::env::var("HAKO_PARSER_STAGE3").ok().as_deref() == Some("1") {
|
||||
warn_alias_once("HAKO_PARSER_STAGE3", "NYASH_PARSER_STAGE3");
|
||||
return true;
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
/// Parser gate for Block‑Postfix Catch acceptance
|
||||
@ -578,3 +596,72 @@ pub fn oob_strict_fail() -> bool {
|
||||
.or_else(|| env_flag("NYASH_OOB_STRICT_FAIL"))
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
/// Primary verification route: return true when Hakorune VM is requested as primary.
|
||||
/// Accepts HAKO_VERIFY_PRIMARY=hakovm (preferred) or legacy HAKO_ROUTE_HAKOVM=1 (deprecated, warns).
|
||||
pub fn verify_primary_is_hakovm() -> bool {
|
||||
if std::env::var("HAKO_VERIFY_PRIMARY").ok().as_deref() == Some("hakovm") {
|
||||
return true;
|
||||
}
|
||||
if env_bool("HAKO_ROUTE_HAKOVM") {
|
||||
warn_alias_once("HAKO_ROUTE_HAKOVM", "HAKO_VERIFY_PRIMARY=hakovm");
|
||||
return true;
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
fn warn_alias_once(alias: &str, primary: &str) {
|
||||
let set = WARNED_ALIASES.get_or_init(|| Mutex::new(HashSet::new()));
|
||||
if let Ok(mut s) = set.lock() {
|
||||
if !s.contains(alias) {
|
||||
eprintln!("[deprecate/env] '{}' is deprecated; use '{}'", alias, primary);
|
||||
s.insert(alias.to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---- ENV consolidation helpers (Phase 21.10/22.1) ----
|
||||
/// LLVM opt level (primary: NYASH_LLVM_OPT_LEVEL; alias: HAKO_LLVM_OPT_LEVEL)
|
||||
/// Returns string level (e.g., "0", "1", ...). Default: "0" when unset.
|
||||
pub fn llvm_opt_level() -> String {
|
||||
if let Some(v) = std::env::var("NYASH_LLVM_OPT_LEVEL").ok() {
|
||||
return v;
|
||||
}
|
||||
if let Some(v) = std::env::var("HAKO_LLVM_OPT_LEVEL").ok() {
|
||||
warn_alias_once("HAKO_LLVM_OPT_LEVEL", "NYASH_LLVM_OPT_LEVEL");
|
||||
return v;
|
||||
}
|
||||
"0".to_string()
|
||||
}
|
||||
|
||||
/// Gate‑C(Core) route request (primary: NYASH_GATE_C_CORE; alias: HAKO_GATE_C_CORE)
|
||||
pub fn gate_c_core() -> bool {
|
||||
if env_bool("NYASH_GATE_C_CORE") { return true; }
|
||||
if env_bool("HAKO_GATE_C_CORE") {
|
||||
warn_alias_once("HAKO_GATE_C_CORE", "NYASH_GATE_C_CORE");
|
||||
return true;
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
/// Consolidated toggle for selfhost NY compiler pipeline.
|
||||
/// Primary: NYASH_USE_NY_COMPILER=0|1. Legacy disables accepted (with warning):
|
||||
/// NYASH_DISABLE_NY_COMPILER/HAKO_DISABLE_NY_COMPILER (any true value disables).
|
||||
pub fn use_ny_compiler() -> bool {
|
||||
// Primary knob takes precedence when explicitly set
|
||||
if let Some(v) = std::env::var("NYASH_USE_NY_COMPILER").ok() {
|
||||
let lv = v.trim().to_ascii_lowercase();
|
||||
return lv == "1" || lv == "true" || lv == "on";
|
||||
}
|
||||
// Legacy disable aliases — if any is true, treat as disabled and warn
|
||||
if env_bool("NYASH_DISABLE_NY_COMPILER") {
|
||||
warn_alias_once("NYASH_DISABLE_NY_COMPILER", "NYASH_USE_NY_COMPILER=0");
|
||||
return false;
|
||||
}
|
||||
if env_bool("HAKO_DISABLE_NY_COMPILER") {
|
||||
warn_alias_once("HAKO_DISABLE_NY_COMPILER", "NYASH_USE_NY_COMPILER=0");
|
||||
return false;
|
||||
}
|
||||
// Default: ON (MVP selfhost path)
|
||||
true
|
||||
}
|
||||
|
||||
@ -24,8 +24,8 @@ def lower_function(builder, func_data: Dict[str, Any]):
|
||||
|
||||
# Determine function signature
|
||||
if name == "ny_main":
|
||||
# Special case: ny_main returns i32
|
||||
func_ty = ir.FunctionType(builder.i32, [])
|
||||
# Special case: ny_main returns i64 to match runtime (nyrt) expectations
|
||||
func_ty = ir.FunctionType(builder.i64, [])
|
||||
else:
|
||||
# Default: i64(i64, ...) signature; derive arity from '/N' suffix when params missing
|
||||
m = re.search(r"/(\d+)$", name)
|
||||
|
||||
@ -45,7 +45,23 @@ def lower_binop(
|
||||
lhs_val = ir.Constant(ir.IntType(64), 0)
|
||||
if rhs_val is None:
|
||||
rhs_val = ir.Constant(ir.IntType(64), 0)
|
||||
|
||||
# Normalize operation aliases (textual -> symbolic)
|
||||
op_raw = op or ''
|
||||
op_l = op_raw.lower()
|
||||
alias = {
|
||||
'add': '+', 'plus': '+',
|
||||
'sub': '-', 'minus': '-',
|
||||
'mul': '*', 'times': '*',
|
||||
'div': '/',
|
||||
'mod': '%', 'rem': '%',
|
||||
'band': '&', 'bitand': '&',
|
||||
'bor': '|', 'bitor': '|',
|
||||
'bxor': '^', 'xor': '^',
|
||||
'shl': '<<',
|
||||
'shr': '>>', 'ashr': '>>',
|
||||
}
|
||||
op = alias.get(op_l, op_raw)
|
||||
|
||||
# Relational/equality operators delegate to compare
|
||||
if op in ('==','!=','<','>','<=','>='):
|
||||
# Delegate to compare with resolver/preds context to maintain dominance via localization
|
||||
|
||||
@ -97,9 +97,16 @@ def lower_return(
|
||||
# Pointer type - null
|
||||
ret_val = ir.Constant(return_type, None)
|
||||
|
||||
# If still zero-like and we have predecessor snapshots, synthesize a minimal PHI at block head.
|
||||
# If still zero-like (typed zero) and we have predecessor snapshots, synthesize a minimal PHI at block head.
|
||||
try:
|
||||
zero_like = isinstance(ret_val, ir.Constant)
|
||||
zero_like = False
|
||||
if isinstance(ret_val, ir.Constant):
|
||||
if isinstance(return_type, ir.IntType):
|
||||
zero_like = (str(ret_val) == str(ir.Constant(return_type, 0)))
|
||||
elif isinstance(return_type, ir.DoubleType):
|
||||
zero_like = (str(ret_val) == str(ir.Constant(return_type, 0.0)))
|
||||
elif isinstance(return_type, ir.PointerType):
|
||||
zero_like = (str(ret_val) == str(ir.Constant(return_type, None)))
|
||||
if zero_like and preds is not None and block_end_values is not None and bb_map is not None and isinstance(value_id, int):
|
||||
# Derive current block id from name like 'bb3'
|
||||
cur_bid = None
|
||||
|
||||
@ -152,7 +152,8 @@ class NyashLLVMBuilder:
|
||||
else:
|
||||
arity = int(m.group(1)) if m else len(params_list)
|
||||
if name == "ny_main":
|
||||
fty = ir.FunctionType(self.i32, [])
|
||||
# Align with runtime expectation: ny_main returns i64
|
||||
fty = ir.FunctionType(self.i64, [])
|
||||
else:
|
||||
fty = ir.FunctionType(self.i64, [self.i64] * arity)
|
||||
exists = False
|
||||
|
||||
@ -13,8 +13,7 @@ fn main() {
|
||||
// If NYASH_VERIFY_JSON is present and route is requested, execute and exit.
|
||||
// This avoids plugin host/registry initialization and keeps output minimal.
|
||||
let has_json = std::env::var("NYASH_VERIFY_JSON").is_ok();
|
||||
let route = nyash_rust::config::env::env_bool("HAKO_ROUTE_HAKOVM")
|
||||
|| std::env::var("HAKO_VERIFY_PRIMARY").ok().as_deref() == Some("hakovm");
|
||||
let route = nyash_rust::config::env::verify_primary_is_hakovm();
|
||||
// Force flag may allow hv1-inline without route
|
||||
let force_hv1_flag = nyash_rust::config::env::env_bool("HAKO_VERIFY_V1_FORCE_HAKOVM");
|
||||
if has_json && (route || force_hv1_flag) {
|
||||
|
||||
@ -12,30 +12,9 @@ pub(crate) fn execute_file_with_backend(runner: &NyashRunner, filename: &str) {
|
||||
// Note: hv1 direct route is now handled at main.rs entry point (before NyashRunner creation).
|
||||
// This function is only called after plugins and runner initialization have already occurred.
|
||||
|
||||
// Selfhost pipeline (Ny -> JSON v0)
|
||||
// Default: ON. Backward‑compat envs:
|
||||
// - NYASH_USE_NY_COMPILER={1|true|on} to force ON
|
||||
// - NYASH_USE_NY_COMPILER={0|false|off} or NYASH_DISABLE_NY_COMPILER/HAKO_DISABLE_NY_COMPILER to disable
|
||||
let mut use_selfhost = true;
|
||||
if let Ok(v) = std::env::var("NYASH_USE_NY_COMPILER") {
|
||||
let lv = v.trim().to_ascii_lowercase();
|
||||
use_selfhost = matches!(lv.as_str(), "1" | "true" | "on");
|
||||
}
|
||||
let disabled = std::env::var("NYASH_DISABLE_NY_COMPILER")
|
||||
.ok()
|
||||
.map(|v| {
|
||||
let lv = v.trim().to_ascii_lowercase();
|
||||
matches!(lv.as_str(), "1" | "true" | "on")
|
||||
})
|
||||
.unwrap_or(false)
|
||||
|| std::env::var("HAKO_DISABLE_NY_COMPILER")
|
||||
.ok()
|
||||
.map(|v| {
|
||||
let lv = v.trim().to_ascii_lowercase();
|
||||
matches!(lv.as_str(), "1" | "true" | "on")
|
||||
})
|
||||
.unwrap_or(false);
|
||||
if use_selfhost && !disabled {
|
||||
// Selfhost pipeline (Ny -> JSON v0) — consolidated env toggle
|
||||
// Primary: NYASH_USE_NY_COMPILER=0|1; legacy disables accepted with deprecation warning
|
||||
if crate::config::env::use_ny_compiler() {
|
||||
if runner.try_run_selfhost_pipeline(filename) {
|
||||
return;
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user