* Copyright (c) 2021-2026 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "JSemitter.h"
#include "compiler/core/pandagen.h"
#include "varbinder/varbinder.h"
#include "parser/program/program.h"
#include "assembly-program.h"
#include "public/public.h"
namespace ark::es2panda::compiler {
pandasm::Function *JSFunctionEmitter::GenFunctionSignature()
{
#ifdef PANDA_WITH_ECMASCRIPT
auto *func = new pandasm::Function(Cg()->InternalName().Mutf8(), panda_file::SourceLang::ECMASCRIPT);
GetProgramElement()->SetFunction(func);
size_t paramCount = Cg()->InternalParamCount();
func->params.reserve(paramCount);
for (uint32_t i = 0; i < paramCount; ++i) {
func->params.emplace_back(pandasm::Type("any", 0), panda_file::SourceLang::ECMASCRIPT);
}
func->regsNum = VReg::REG_START - Cg()->TotalRegsNum();
func->returnType = pandasm::Type("any", 0);
return func;
#else
ES2PANDA_UNREACHABLE();
#endif
}
void JSFunctionEmitter::GenVariableSignature(pandasm::debuginfo::LocalVariable &variableDebug,
[[maybe_unused]] varbinder::LocalVariable *variable) const
{
variableDebug.signature = "any";
variableDebug.signatureType = "any";
}
void JSFunctionEmitter::GenSourceFileDebugInfo(pandasm::Function *func)
{
func->sourceFile = std::string {Cg()->VarBinder()->Program()->RelativeFilePath(Cg()->Context())};
if (!Cg()->IsDebug()) {
return;
}
if (Cg()->RootNode()->IsProgram()) {
func->sourceCode = SourceCode().EscapeSymbol<util::StringView::Mutf8Encode>();
}
}
void JSFunctionEmitter::GenFunctionAnnotations(pandasm::Function *func)
{
pandasm::AnnotationData funcAnnotationData("_ESAnnotation");
pandasm::AnnotationElement icSizeAnnotationElement(
"icSize", std::make_unique<pandasm::ScalarValue>(
pandasm::ScalarValue::Create<pandasm::Value::Type::U32>(Pg()->IcSize())));
funcAnnotationData.AddElement(std::move(icSizeAnnotationElement));
pandasm::AnnotationElement parameterLengthAnnotationElement(
"parameterLength", std::make_unique<pandasm::ScalarValue>(
pandasm::ScalarValue::Create<pandasm::Value::Type::U32>(Pg()->FormalParametersCount())));
funcAnnotationData.AddElement(std::move(parameterLengthAnnotationElement));
pandasm::AnnotationElement funcNameAnnotationElement(
"funcName", std::make_unique<pandasm::ScalarValue>(
pandasm::ScalarValue::Create<pandasm::Value::Type::STRING>(Pg()->FunctionName().Mutf8())));
funcAnnotationData.AddElement(std::move(funcNameAnnotationElement));
func->metadata->AddAnnotations({funcAnnotationData});
}
void JSEmitter::EmitRecords()
{
#ifdef PANDA_WITH_ECMASCRIPT
Program()->lang = panda_file::SourceLang::ECMASCRIPT;
GenESAnnotationRecord();
GenESModuleModeRecord(Context()->config->options->IsModule());
#else
ES2PANDA_UNREACHABLE();
#endif
}
void JSEmitter::GenESAnnotationRecord()
{
auto annotationRecord = pandasm::Record("_ESAnnotation", Program()->lang);
annotationRecord.metadata->SetAttribute("external");
annotationRecord.metadata->SetAccessFlags(ACC_ANNOTATION);
Program()->recordTable.emplace(annotationRecord.name, std::move(annotationRecord));
}
void JSEmitter::GenESModuleModeRecord(bool isModule)
{
auto modeRecord = pandasm::Record("_ESModuleMode", Program()->lang);
modeRecord.metadata->SetAccessFlags(ACC_PUBLIC);
auto modeField = pandasm::Field(Program()->lang);
modeField.name = "isModule";
modeField.type = pandasm::Type("u8", 0);
modeField.metadata->SetValue(
pandasm::ScalarValue::Create<pandasm::Value::Type::U8>(static_cast<uint8_t>(isModule)));
modeRecord.fieldList.emplace_back(std::move(modeField));
Program()->recordTable.emplace(modeRecord.name, std::move(modeRecord));
}
}