158 lines
4.9 KiB
Plaintext
158 lines
4.9 KiB
Plaintext
|
|
// LLVM PHI Instruction Box — Python phi.py のHakorune実装
|
|||
|
|
// MIR PHI命令(SSA値マージング)をJSON形式に変換し、C++バックエンドに渡す
|
|||
|
|
//
|
|||
|
|
// PHI命令はSSA形式で制御フローの合流点における値のマージを表現する
|
|||
|
|
// 例: if (cond) { x = 1 } else { x = 2 } → x = PHI(1 from bb1, 2 from bb2)
|
|||
|
|
|
|||
|
|
static box LLVMPhiInstructionBox {
|
|||
|
|
|
|||
|
|
// メインエントリーポイント - Pythonのlower_phi()に相当
|
|||
|
|
// Stage 1: 基本PHI生成(JSON生成のみ)
|
|||
|
|
//
|
|||
|
|
// Args:
|
|||
|
|
// dst: 出力先レジスタID(整数)
|
|||
|
|
// incoming_list: incoming値のリスト
|
|||
|
|
// 形式: [{"value":1,"block":1}, {"value":2,"block":2}, ...]
|
|||
|
|
// - value: 入力値のレジスタID
|
|||
|
|
// - block: その値が来る基本ブロックID
|
|||
|
|
//
|
|||
|
|
// Returns:
|
|||
|
|
// JSON文字列: {"op":"phi","dst":5,"incoming":[...]}
|
|||
|
|
//
|
|||
|
|
lower_phi(dst, incoming_list) {
|
|||
|
|
// 空チェック: incoming が空の場合は 0 定数を返す
|
|||
|
|
// Python: phi.py 34-37行の動作と同じ
|
|||
|
|
if incoming_list == null {
|
|||
|
|
return me._phi_empty_fallback(dst)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
local list_len = incoming_list.length()
|
|||
|
|
if list_len == 0 {
|
|||
|
|
return me._phi_empty_fallback(dst)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// incoming配列をJSON化
|
|||
|
|
local incoming_json = me._build_incoming_array(incoming_list)
|
|||
|
|
|
|||
|
|
// PHI命令のJSON形式を生成
|
|||
|
|
// {"op":"phi","dst":5,"incoming":[{"value":1,"block":1},{"value":2,"block":2}]}
|
|||
|
|
return "{\"op\":\"phi\",\"dst\":" + dst + ",\"incoming\":" + incoming_json + "}"
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 空のPHI: 0定数にフォールバック
|
|||
|
|
// Python: phi.py 34-37行
|
|||
|
|
_phi_empty_fallback(dst) {
|
|||
|
|
// No incoming edges - use zero constant
|
|||
|
|
return "{\"op\":\"const\",\"dst\":" + dst + ",\"value\":{\"type\":\"i64\",\"value\":0}}"
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// incoming配列のJSON化
|
|||
|
|
//
|
|||
|
|
// Args:
|
|||
|
|
// incoming_list: [{"value":1,"block":1}, {"value":2,"block":2}, ...]
|
|||
|
|
//
|
|||
|
|
// Returns:
|
|||
|
|
// JSON配列文字列: [{"value":1,"block":1},{"value":2,"block":2}]
|
|||
|
|
//
|
|||
|
|
_build_incoming_array(incoming_list) {
|
|||
|
|
local result = "["
|
|||
|
|
local first = 1
|
|||
|
|
|
|||
|
|
// 各incoming要素をJSON化
|
|||
|
|
local i = 0
|
|||
|
|
local len = incoming_list.length()
|
|||
|
|
|
|||
|
|
loop(i < len) {
|
|||
|
|
local item = incoming_list.get(i)
|
|||
|
|
|
|||
|
|
// item は {"value":X, "block":Y} の形式のMapBox
|
|||
|
|
local value_id = item.get("value")
|
|||
|
|
local block_id = item.get("block")
|
|||
|
|
|
|||
|
|
// カンマ区切り(最初の要素以外)
|
|||
|
|
if first == 0 {
|
|||
|
|
result = result + ","
|
|||
|
|
}
|
|||
|
|
first = 0
|
|||
|
|
|
|||
|
|
// {"value":X,"block":Y} 形式で追加
|
|||
|
|
result = result + "{\"value\":" + value_id + ",\"block\":" + block_id + "}"
|
|||
|
|
|
|||
|
|
i = i + 1
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
result = result + "]"
|
|||
|
|
return result
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// デバッグ用 - 生成された命令の確認
|
|||
|
|
debug_phi(dst, incoming_list) {
|
|||
|
|
local json = me.lower_phi(dst, incoming_list)
|
|||
|
|
print("Generated PHI instruction: " + json)
|
|||
|
|
return json
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Stage 2 プレースホルダー: Block End Values管理(将来実装)
|
|||
|
|
// Python: phi.py 69-79行の block_end_values スナップショット処理
|
|||
|
|
// 注: Hakorune版では不要(C++バックエンドが処理)
|
|||
|
|
lower_phi_with_snapshot(dst, incoming_list, block_end_values) {
|
|||
|
|
// 現時点では基本版と同じ動作
|
|||
|
|
return me.lower_phi(dst, incoming_list)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Stage 3 プレースホルダー: 型変換処理(将来実装)
|
|||
|
|
// Python: phi.py 84-103行の型変換処理
|
|||
|
|
// 注: Hakorune版では不要(C++バックエンドが処理)
|
|||
|
|
lower_phi_with_type_info(dst, incoming_list, type_info) {
|
|||
|
|
// 現時点では基本版と同じ動作
|
|||
|
|
return me.lower_phi(dst, incoming_list)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Stage 4 プレースホルダー: Strict Mode(将来実装)
|
|||
|
|
// Python: phi.py 118-121行の NYASH_LLVM_PHI_STRICT チェック
|
|||
|
|
// 注: C++バックエンドで実装予定
|
|||
|
|
lower_phi_strict(dst, incoming_list, strict_mode) {
|
|||
|
|
// 現時点では基本版と同じ動作
|
|||
|
|
return me.lower_phi(dst, incoming_list)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Stage 5 プレースホルダー: 文字列性伝播(将来実装)
|
|||
|
|
// Python: phi.py 131-142行の resolver.is_stringish() 処理
|
|||
|
|
// 注: C++バックエンドで実装予定
|
|||
|
|
lower_phi_with_string_propagation(dst, incoming_list, resolver) {
|
|||
|
|
// 現時点では基本版と同じ動作
|
|||
|
|
return me.lower_phi(dst, incoming_list)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ヘルパー: incoming要素の検証(デバッグ用)
|
|||
|
|
_validate_incoming(incoming_list) {
|
|||
|
|
if incoming_list == null {
|
|||
|
|
return 0
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
local len = incoming_list.length()
|
|||
|
|
if len == 0 {
|
|||
|
|
return 0
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 各要素が {"value":X, "block":Y} 形式か確認
|
|||
|
|
local i = 0
|
|||
|
|
loop(i < len) {
|
|||
|
|
local item = incoming_list.get(i)
|
|||
|
|
|
|||
|
|
// value と block フィールドが存在するか
|
|||
|
|
local has_value = item.has("value")
|
|||
|
|
local has_block = item.has("block")
|
|||
|
|
|
|||
|
|
if has_value == 0 || has_block == 0 {
|
|||
|
|
print("WARNING: Invalid incoming item at index " + i)
|
|||
|
|
return 0
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
i = i + 1
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return 1
|
|||
|
|
}
|
|||
|
|
}
|