背景说明

在编译器中端开发中,需要将 SlowPathLowering 中的字节码 lowering 逻辑迁移到 xxxGraphBuilder。这两者使用不同的 API 和架构:

  • SlowPathLowering:基于 Circuit 的门级 IR,使用 GateRefGateAccessorCircuitBuilder 等 API
  • xxxGraphBuilder:基于图结构的 IR,使用 ValueVertexControlVertexNewVertex 等 API,采用类似 V8 MaglevCFG (控制流图) 结构

迁移难点包括:

  1. IR 结构差异:从扁平的 Circuit 迁移到分层结构的 CFG
  2. API 映射GateRefValueVertex*CircuitBuilderNewVertex<XxxVertex>
  3. 参数获取acc_.GetValueIn()GetConstDataId()/GetImmediate()/LoadRegister()
  4. 条件编译:正确处理 #if ECMASCRIPT_ENABLE_IC 等宏

AI 需要理解两套 API 的对应关系,并正确处理字节码输入格式。


案例:批量生成 LdLexVar & StLexVar CommonStub

提示词

帮我生成一个 CommonStub,并且加上 call_signature,生成在 standalone/arkcompiler/ets_runtime/ecmascript/compiler/common_stubs.cpp,内容使用 void SlowPathLowering::LowerLdLexVar(GateRef gate),并给 void xxxGraphBuilder::LowerLdLexVar() 使用

同理,StLexVar 也参考 void SlowPathLowering::LowerStLexVar(GateRef gate) 构建 CommonStub,并且 void xxxGraphBuilder::LowerStLexVar() 会调用这个 stub。

AI 生成的代码

1. call_signature.h / common_stub_csigns.h(添加宏定义)
V(LdLexVar)
V(StLexVar)
2. call_signature.cpp(添加签名定义)
DEF_CALL_SIGNATURE(LdLexVar)
{
    CallSignature signature("LdLexVar", 0, 4, ArgumentsOrder::DEFAULT_ORDER, VariableType::JS_ANY());
    *callSign = signature;
    std::array<VariableType, 4> params = {
        VariableType::NATIVE_POINTER(),  // glue
        VariableType::INT32(),           // level
        VariableType::INT32(),           // slot
        VariableType::JS_ANY()           // currentEnv
    };
    callSign->SetParameters(params.data());
    callSign->SetCallConv(CallSignature::CallConv::CCallConv);
}

DEF_CALL_SIGNATURE(StLexVar)
{
    CallSignature signature("StLexVar", 0, 5, ArgumentsOrder::DEFAULT_ORDER, VariableType::JS_ANY());
    *callSign = signature;
    std::array<VariableType, 5> params = {
        VariableType::NATIVE_POINTER(),  // glue
        VariableType::INT32(),           // level
        VariableType::INT32(),           // slot
        VariableType::JS_ANY(),          // currentEnv
        VariableType::JS_ANY()           // value
    };
    callSign->SetParameters(params.data());
    callSign->SetCallConv(CallSignature::CallConv::CCallConv);
}
3. common_stubs.cpp(添加 Stub 实现)
void LdLexVarStubBuilder::GenerateCircuit()
{
    auto env = GetEnvironment();
    GateRef glue = PtrArgument(0);
    GateRef level = Int32Argument(1);
    GateRef slot = Int32Argument(2);
    DEFVARIABLE(currentEnv, VariableType::JS_ANY(), TaggedArgument(3));
    GateRef index = Int32(LexicalEnv::PARENT_ENV_INDEX);
    Label exit(env);
    Label loopHead(env);
    Label loopEnd(env);

    DEFVARIABLE(i, VariableType::INT32(), Int32(0));
    BRANCH(Int32LessThan(*i, level), &loopHead, &exit);
    Bind(&loopHead);
    {
        currentEnv = GetValueFromTaggedArray(glue, *currentEnv, index);
        i = Int32Add(*i, Int32(1));
        BRANCH(Int32LessThan(*i, level), &loopEnd, &exit);
    }
    Bind(&loopEnd);
    {
        LoopEnd(&loopHead);
    }
    Bind(&exit);
    GateRef valueIndex = Int32Add(slot, Int32(LexicalEnv::RESERVED_ENV_LENGTH));
    GateRef result = GetValueFromTaggedArray(glue, *currentEnv, valueIndex);
    Return(result);
}

void StLexVarStubBuilder::GenerateCircuit()
{
    auto env = GetEnvironment();
    GateRef glue = PtrArgument(0);
    GateRef level = Int32Argument(1);
    GateRef slot = Int32Argument(2);
    DEFVARIABLE(currentEnv, VariableType::JS_ANY(), TaggedArgument(3));
    GateRef value = TaggedArgument(4);
    GateRef index = Int32(LexicalEnv::PARENT_ENV_INDEX);
    Label exit(env);
    Label loopHead(env);
    Label loopEnd(env);

    DEFVARIABLE(i, VariableType::INT32(), Int32(0));
    BRANCH(Int32LessThan(*i, level), &loopHead, &exit);
    Bind(&loopHead);
    {
        currentEnv = GetValueFromTaggedArray(glue, *currentEnv, index);
        i = Int32Add(*i, Int32(1));
        BRANCH(Int32LessThan(*i, level), &loopEnd, &exit);
    }
    Bind(&loopEnd);
    {
        LoopEnd(&loopHead);
    }
    Bind(&exit);
    GateRef valueIndex = Int32Add(slot, Int32(LexicalEnv::RESERVED_ENV_LENGTH));
    SetValueToTaggedArray(VariableType::JS_ANY(), glue, *currentEnv, valueIndex, value);
    Return(*currentEnv);
}
4. xxx_graph_builder.cpp(更新调用代码)
void xxxGraphBuilder::LowerLdLexVar()
{
    ValueVertex* level = GetInt32Constant(static_cast<int>(GetImmediate(0)));
    ValueVertex* slot = GetInt32Constant(static_cast<int>(GetImmediate(1)));
    ValueVertex* lexicalEnv = LoadRegister(2);
    ValueVertex* glue = GetGlue();
    SetAcc(NewVertex<CallCommonStubVertex>({glue, level, slot, lexicalEnv}, CommonStubCSigns::LdLexVar));
}

void xxxGraphBuilder::LowerStLexVar()
{
    ValueVertex* level = GetInt32Constant(static_cast<int>(GetImmediate(0)));
    ValueVertex* slot = GetInt32Constant(static_cast<int>(GetImmediate(1)));
    ValueVertex* lexicalEnv = LoadRegister(2);
    ValueVertex* value = GetAcc();
    ValueVertex* glue = GetGlue();
    SetAcc(NewVertex<CallCommonStubVertex>({glue, level, slot, lexicalEnv, value}, CommonStubCSigns::StLexVar));
}

效率对比

代码统计

项目 行数
call_signature.h 2 行
call_signature.cpp 33 行
common_stub_csigns.h 2 行
common_stubs.cpp 60 行
xxx_graph_builder.cpp 13 行
总计 110 行

效率提升

指标 手动编写 AI 辅助 提升
时间消耗 ~40 分钟 ~5 分钟 8x
代码行数 110 行 0 行(直接生成) 100%
正确率 需多次调试 一次生成正确 -
文件修改数 5 个文件 0 个文件(自动修改) -
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐