feat: 维护结构体字段布局的全局静态表

- 新增 STRUCT_LAYOUTS静态字段,用于存储结构体字段布局
- 添加 registerStructLayout 方法,注册结构体字段布局
- 实现 lookupFieldIndex 和 getStructLayout 方法,用于查询字段布局
- 优化跨模块常量导入和查询逻辑
- 重构部分代码,提高可读性和维护性
This commit is contained in:
Luke 2025-08-29 17:43:29 +08:00
parent 37c03cf248
commit 8f59f91766

View File

@ -3,6 +3,7 @@ package org.jcnc.snow.compiler.ir.builder;
import org.jcnc.snow.compiler.ir.core.IRFunction; import org.jcnc.snow.compiler.ir.core.IRFunction;
import org.jcnc.snow.compiler.ir.value.IRVirtualRegister; import org.jcnc.snow.compiler.ir.value.IRVirtualRegister;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -16,6 +17,7 @@ import java.util.Map;
* <li>支持变量的类型信息记录与查询</li> * <li>支持变量的类型信息记录与查询</li>
* <li>支持变量的编译期常量值记录与查询便于常量折叠等优化</li> * <li>支持变量的编译期常量值记录与查询便于常量折叠等优化</li>
* <li>支持跨模块全局常量 ModuleA.a查找</li> * <li>支持跨模块全局常量 ModuleA.a查找</li>
* <li>维护结构体字段布局全局共享字段名 槽位下标用于对象字段读写</li>
* </ul> * </ul>
*/ */
final class IRBuilderScope { final class IRBuilderScope {
@ -28,14 +30,23 @@ final class IRBuilderScope {
private final Map<String, Object> varConstValues = new HashMap<>(); private final Map<String, Object> varConstValues = new HashMap<>();
/** /**
* 额外存放跨模块导入的全局常量 * 存放跨模块导入的全局常量 ModuleA.a
* key 形如 "ModuleA.a" value 为其常量值 * 键为 "ModuleA.a"值为常量值
*/ */
private final Map<String, Object> externalConsts = new HashMap<>(); private final Map<String, Object> externalConsts = new HashMap<>();
/** 当前作用域所绑定的 IRFunction 实例 */ /**
* 结构体字段布局的全局静态表
* 结构体名 (字段名 槽位下标)
* 静态表设计确保所有作用域所有 IR 构建都能访问同一套布局
*/
private static final Map<String, Map<String, Integer>> STRUCT_LAYOUTS = new HashMap<>();
/** 当前作用域所绑定的 IRFunction 实例,用于变量分配新寄存器等。 */
private IRFunction fn; private IRFunction fn;
// ---------------- 作用域与变量 ----------------
/** /**
* 绑定当前作用域到指定 IRFunction * 绑定当前作用域到指定 IRFunction
* *
@ -55,7 +66,7 @@ final class IRBuilderScope {
IRVirtualRegister reg = fn.newRegister(); IRVirtualRegister reg = fn.newRegister();
vars.put(name, reg); vars.put(name, reg);
varTypes.put(name, type); varTypes.put(name, type);
varConstValues.remove(name); varConstValues.remove(name); // 声明新变量即清除原常量绑定
} }
/** /**
@ -68,7 +79,7 @@ final class IRBuilderScope {
void declare(String name, String type, IRVirtualRegister reg) { void declare(String name, String type, IRVirtualRegister reg) {
vars.put(name, reg); vars.put(name, reg);
varTypes.put(name, type); varTypes.put(name, type);
varConstValues.remove(name); varConstValues.remove(name); // 重复声明也会清除常量绑定
} }
/** /**
@ -104,16 +115,18 @@ final class IRBuilderScope {
/** /**
* 获取变量名到类型名映射的不可变副本 * 获取变量名到类型名映射的不可变副本
* *
* @return 变量名类型名映射的只读视图 * @return 变量名类型名映射的只读视图用于调试/全局分析
*/ */
Map<String, String> getVarTypes() { Map<String, String> getVarTypes() {
return Map.copyOf(varTypes); return Collections.unmodifiableMap(varTypes);
} }
// ---------------- 编译期常量相关接口 ---------------- // ---------------- 编译期常量相关接口 ----------------
/** /**
* 设置变量的编译期常量值本地变量 * 设置变量的编译期常量值本地变量
* <p>
* 便于 IR 生成时做常量折叠等优化value null 则清除绑定
* *
* @param name 变量名称 * @param name 变量名称
* @param value 常量值null 表示清除 * @param value 常量值null 表示清除
@ -124,9 +137,9 @@ final class IRBuilderScope {
} }
/** /**
* 获取变量的编译期常量值本地变量或导入的外部常量 * 获取变量的编译期常量值优先本地再查跨模块导入
* <br> * <p>
* 优先查找本地常量未命中再查外部 "ModuleA.a" * 常用于优化与折叠支持 "Module.a" 这类跨模块全局常量查找
* *
* @param name 变量名称或"模块名.常量名" * @param name 变量名称或"模块名.常量名"
* @return 编译期常量值 null * @return 编译期常量值 null
@ -134,7 +147,7 @@ final class IRBuilderScope {
Object getConstValue(String name) { Object getConstValue(String name) {
Object v = varConstValues.get(name); Object v = varConstValues.get(name);
if (v != null) return v; if (v != null) return v;
// 支持跨模块常量/全局变量 // 支持跨模块常量/全局变量 "ModuleA.a"
return externalConsts.get(name); return externalConsts.get(name);
} }
@ -158,4 +171,60 @@ final class IRBuilderScope {
void importExternalConst(String qualifiedName, Object value) { void importExternalConst(String qualifiedName, Object value) {
externalConsts.put(qualifiedName, value); externalConsts.put(qualifiedName, value);
} }
// ---------------- 结构体字段布局全局静态 ----------------
/**
* 全局注册结构体的字段布局映射字段名 -> 槽位下标
* 一般在语义分析/IR 前期由类型系统收集后调用
*
* @param structName 结构体名建议为简单名 "Animal"如有模块前缀也可
* @param fieldToIndex 字段名到下标的映射下标从 0 递增
*/
static void registerStructLayout(String structName, Map<String, Integer> fieldToIndex) {
if (structName == null || fieldToIndex == null) return;
// 覆盖式注册方便增量/重复编译时刷新
STRUCT_LAYOUTS.put(structName, new HashMap<>(fieldToIndex));
}
/**
* 查询字段槽位下标
* 支持模块.结构体及简单名两种写法自动兼容
*
* @param structName 结构体名"Module.Struct" "Struct"
* @param fieldName 字段名
* @return 槽位下标若未知返回 null
*/
Integer lookupFieldIndex(String structName, String fieldName) {
// 先按原样查
Map<String, Integer> layout = STRUCT_LAYOUTS.get(structName);
// 兼容 模块.结构体 的写法若没命中退化为简单名再查
if (layout == null && structName != null) {
int dot = structName.lastIndexOf('.');
if (dot >= 0 && dot + 1 < structName.length()) {
String simple = structName.substring(dot + 1);
layout = STRUCT_LAYOUTS.get(simple);
}
}
if (layout == null) return null;
return layout.get(fieldName);
}
/**
* 读取某结构体的完整字段布局返回只读 Map
* 支持模块.结构体及简单名两种写法
*
* @param structName 结构体名
* @return 字段名到下标映射的只读视图 null
*/
Map<String, Integer> getStructLayout(String structName) {
Map<String, Integer> layout = STRUCT_LAYOUTS.get(structName);
if (layout == null && structName != null) {
int dot = structName.lastIndexOf('.');
if (dot >= 0 && dot + 1 < structName.length()) {
layout = STRUCT_LAYOUTS.get(structName.substring(dot + 1));
}
}
return layout == null ? null : Collections.unmodifiableMap(layout);
}
} }