1/*
2 * Copyright (c) 2021 - 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "JSemitter.h"
17
18#include "compiler/core/pandagen.h"
19#include "varbinder/varbinder.h"
20#include "parser/program/program.h"
21#include "assembly-program.h"
22#include "public/public.h"
23
24namespace ark::es2panda::compiler {
25pandasm::Function *JSFunctionEmitter::GenFunctionSignature()
26{
27#ifdef PANDA_WITH_ECMASCRIPT
28    auto *func = new pandasm::Function(Cg()->InternalName().Mutf8(), panda_file::SourceLang::ECMASCRIPT);
29    GetProgramElement()->SetFunction(func);
30
31    size_t paramCount = Cg()->InternalParamCount();
32    func->params.reserve(paramCount);
33
34    for (uint32_t i = 0; i < paramCount; ++i) {
35        func->params.emplace_back(pandasm::Type("any", 0), panda_file::SourceLang::ECMASCRIPT);
36    }
37
38    func->regsNum = VReg::REG_START - Cg()->TotalRegsNum();
39    func->returnType = pandasm::Type("any", 0);
40
41    return func;
42#else
43    UNREACHABLE();
44#endif
45}
46
47void JSFunctionEmitter::GenVariableSignature(pandasm::debuginfo::LocalVariable &variableDebug,
48                                             [[maybe_unused]] varbinder::LocalVariable *variable) const
49{
50    variableDebug.signature = "any";
51    variableDebug.signatureType = "any";
52}
53
54void JSFunctionEmitter::GenFunctionAnnotations(pandasm::Function *func)
55{
56    pandasm::AnnotationData funcAnnotationData("_ESAnnotation");
57    pandasm::AnnotationElement icSizeAnnotationElement(
58        "icSize", std::make_unique<pandasm::ScalarValue>(
59                      pandasm::ScalarValue::Create<pandasm::Value::Type::U32>(Pg()->IcSize())));
60    funcAnnotationData.AddElement(std::move(icSizeAnnotationElement));
61
62    pandasm::AnnotationElement parameterLengthAnnotationElement(
63        "parameterLength", std::make_unique<pandasm::ScalarValue>(
64                               pandasm::ScalarValue::Create<pandasm::Value::Type::U32>(Pg()->FormalParametersCount())));
65    funcAnnotationData.AddElement(std::move(parameterLengthAnnotationElement));
66
67    pandasm::AnnotationElement funcNameAnnotationElement(
68        "funcName", std::make_unique<pandasm::ScalarValue>(
69                        pandasm::ScalarValue::Create<pandasm::Value::Type::STRING>(Pg()->FunctionName().Mutf8())));
70    funcAnnotationData.AddElement(std::move(funcNameAnnotationElement));
71
72    func->metadata->AddAnnotations({funcAnnotationData});
73}
74
75void JSEmitter::GenAnnotation()
76{
77#ifdef PANDA_WITH_ECMASCRIPT
78    Program()->lang = panda_file::SourceLang::ECMASCRIPT;
79    GenESAnnotationRecord();
80    GenESModuleModeRecord(Context()->parserProgram->Kind() == parser::ScriptKind::MODULE);
81#else
82    UNREACHABLE();
83#endif
84}
85
86void JSEmitter::GenESAnnotationRecord()
87{
88    auto annotationRecord = pandasm::Record("_ESAnnotation", Program()->lang);
89    annotationRecord.metadata->SetAttribute("external");
90    annotationRecord.metadata->SetAccessFlags(ACC_ANNOTATION);
91    Program()->recordTable.emplace(annotationRecord.name, std::move(annotationRecord));
92}
93
94void JSEmitter::GenESModuleModeRecord(bool isModule)
95{
96    auto modeRecord = pandasm::Record("_ESModuleMode", Program()->lang);
97    modeRecord.metadata->SetAccessFlags(ACC_PUBLIC);
98
99    auto modeField = pandasm::Field(Program()->lang);
100    modeField.name = "isModule";
101    modeField.type = pandasm::Type("u8", 0);
102    modeField.metadata->SetValue(
103        pandasm::ScalarValue::Create<pandasm::Value::Type::U8>(static_cast<uint8_t>(isModule)));
104
105    modeRecord.fieldList.emplace_back(std::move(modeField));
106
107    Program()->recordTable.emplace(modeRecord.name, std::move(modeRecord));
108}
109}  // namespace ark::es2panda::compiler
110